React Hooks 一步到位

简介: React Hooks 一步到位

useState

用来声明状态变量。

import React, { useState } from 'react';
// ...
const [ count , setCount ] = useState(0);
// ...
  • count 声明的变量
  • setCount 设用来更新变量的函数
  • 0 初始值
  • 多个状态声明不能出现在条件判断语句中

useEffect

用来代替生命周期函数。

import React, { useEffect } from 'react';
 
useEffect(()=>{
    // some code
})
  • 第一次组件渲染和每次组件更新都会执行这个函数
  • useEffect中的函数的执行不会阻碍浏览器更新视图,这些函数是异步的

使用 useEffect 实现类似 componentWillUnmount

useEffect(()=>{
    return () => { 
        // some code
    }
})
  • 返回一个函数实现解绑
  • 但是这样会导致每次状态发生变化,useEffect 都进行解绑
useEffect(()=>{
    return () => { 
        // some code
    }
}, [])

使用第二个参数,制定哪些状态发生变化时再解绑

useContext

跨越组件层级直接传递变量,实现状态共享。

  • useContext 解决的是组件之间值传递的问题
  • redux 解决的是应用中统一管理状态的问题
  • useContext 通过和 useReducer 的配合使用,可以实现类似 Redux 的作用

Outer 组件

import React, { createContext } from 'react'
const ValueContext = createContext()
function Outer(){
    return (
        <>
            <ValueContext.Provider value={'我是传向 Inner 组件的值'}>
                <Inner />
            </ValueContext.Provider>
        </>
    )
}
export default Outer;
  • 使用 createContext 创建 context
  • 使用 createContext 同时生成组件
  • 闭合标签将组件包裹

Inner 组件

import React, { useContext  } from 'react'
const value = useContext(CountContext)
function Inner(){
    return (
        <>
            <p>{value}</p>
        </>
    )
}
export default Inner;

使用 useContext 来使用上下文

useReducer

用来实现类似 redux 功能

import React, { useReducer } from 'react';
 
function Demo(){
    const [ count, dispatch ] = useReducer((state,action)=>{
        switch(action){
            case 'add':
                return state+1
            case 'sub':
                return state-1
            default:
                return state
        }
    },0)
    return (
       <>
           <h2>分数:{count}</h2>
           <button onClick={()=>dispatch('add')}>加</button>
           <button onClick={()=>dispatch('sub')}>减</button>
       </>
    )
}
 
export default Demo
  • state 第一个参数 状态
  • action 控制业务逻辑的判断参数

模拟 Redux

  • useContext:可访问全局状态,避免一层层的传递状态
  • useReducer:通过action的传递,更新复杂逻辑的状态

颜色共享组件 color.js

import React, { createContext,useReducer } from 'react';
 
export const ColorContext = createContext({})
export const UPDATE_COLOR = 'UPDATE_COLOR'
 
const reducer = (state, action) => {
    switch(action.type){
        case UPDATE_COLOR:
            return action.color
        default:
            return state
    }
}
 
export const Color = props => {
    const [color, dispatch] = useReducer(reducer, 'blue')
    return (
        <ColorContext.Provider value = {{color,dispatch}}>
            {props.children}
        </ColorContext.Provider>
    )
}
  • 用 {props.children} 来显示子组件
  • 将 color 和 dispatch 共享出去

showArea.js

import React , { useContext } from 'react';
import { ColorContext } from './color';
 
function ShowArea(){
    const { color } = useContext(ColorContext)
    return (<div style={{ color:color }}>字体颜色为{ color }</div>)
}
 
export default ShowArea
  • 注意 引入 ColorContext 使用了大括号

Buttons.js

import React , { useContext } from 'react';
import { ColorContext, UPDATE_COLOR } from './color'
 
function Buttons(){
    const { dispatch } = useContext(ColorContext)
    return (
        <div>
            <button onClick={()=>{dispatch({type:UPDATE_COLOR,color:"red"})}}>红色</button>
            <button onClick={()=>{dispatch({type:UPDATE_COLOR,color:"yellow"})}}>黄色</button>
        </div>
    )
}
 
export default Buttons

Demo.js

import React, { useReducer } from 'react';
import ShowArea from './ShowArea';
import Buttons from './Buttons';
import { Color } from './color';   //引入Color组件
 
function Demo(){
    return (
        <>
            <Color>
                <ShowArea />
                <Buttons />
            </Color>
        </>
    )
}
 
export default Demo

useMemo

用来解决使用 React hooks 产生的无用渲染的性能问题。

import React , {useState,useMemo} from 'react';
 
function Demo(){
    const [xiaohong , setXiaohong] = useState('小红待客状态')
    const [zhiling , setZhiling] = useState('志玲待客状态')
    return (
        <>
            <button onClick={()=>{setXiaohong(new Date().getTime())}}>小红</button>
            <button onClick={()=>{setZhiling(new Date().getTime()+',志玲向我们走来了')}}>志玲</button>
            <ChildComponent name={xiaohong}>{zhiling}</ChildComponent>
        </>
    )
}
 
function ChildComponent({name,children}){
    function changeXiaohong(name){
        console.log('她来了,她来了。小红向我们走来了')
        return name+',小红向我们走来了'
    }
 
    const actionXiaohong = changeXiaohong(name)
    return (
        <>
            <div>{actionXiaohong}</div>
            <div>{children}</div>
        </>
    )
}
 
export default Demo

点击志玲按钮,小红对应的方法执行,虽然结果没变,但是每次都执行,损耗性能。

function ChildComponent({name,children}){
    function changeXiaohong(name){
        console.log('她来了,她来了。小红向我们走来了')
        return name+',小红向我们走来了'
    }
 
    const actionXiaohong = useMemo(()=>changeXiaohong(name),[name]) 
    return (
        <>
            <div>{actionXiaohong}</div>
            <div>{children}</div>
        </>
    )
}

第二个参数 [name] 匹配成功,才会执行。

useRef

  • 用来获取React JSX中的DOM元素
  • 用来保存变量
import React, { useRef} from 'react';
function Demo(){
    const inputEl = useRef(null)
        inputEl.current.value = "给 input value属性 赋值"
    return (
        <>
            <input ref={inputEl} type="text"/>
        </>
    )
}
 
export default Demo
import React, { useRef, useState, useEffect } from 'react'
 
function Demo(){
    const inputEl = useRef(null)
        inputEl.current.value="给 input value属性 赋值"
 
    const [text, setText] = useState('默认值')
    const textRef = useRef()
 
    useEffect(()=>{
        textRef.current = text
    })
 
    return (
        <>
            <input ref={inputEl} type="text"/>
            <input value={text} onChange={(e)=>{setText(e.target.value)}} />
        </>
    )
}
 
export default Demo
  • text 每次发生变化,将值保存到 useRef 中
  • 使用 useEffect 实现每次状态变化都进行变量重新赋值
  • 很少用到这个功能(保存变量)

自定义 Hooks

编写自定义函数实现获取浏览器窗口

import React, { useState, useEffect, useCallback } from 'react';
 
function useWinSize(){
    const [ size , setSize] = useState({
        width:document.documentElement.clientWidth,
        height:document.documentElement.clientHeight
    })
 
    const onResize = useCallback(()=>{
        setSize({
            width: document.documentElement.clientWidth,
            height: document.documentElement.clientHeight
        })
    },[])
 
    useEffect(()=>{
        window.addEventListener('resize',onResize)
        return ()=>{
            window.removeEventListener('resize',onResize)
        }
    },[])
 
    return size;
}
 
function Demo(){
    const size = useWinSize()
    return (
        <div>页面Size:{size.width} x {size.height}</div>
    )
}
 
export default Demo 
  • 命名要使用 use 开头以确认该函数是自定义 Hook 而不是组件
  • useCallback 用来缓存方法 ( useMemo 是为了缓存变量)
  • 第一次进入方法时用 useEffect 来注册 resize 监听事件
  • 防止一直监听所以在方法移除时,使用return的方式移除监听
  • 最后在 Demo 组件中使用

文章参考

  • 官方文档
  • 哔哩哔哩up主技术胖的 视频


相关文章
|
1月前
|
前端开发 测试技术 开发工具
探索前端框架React Hooks的优势与应用
本文将深入探讨前端框架React Hooks的优势与应用。通过分析React Hooks的特性以及实际应用案例,帮助读者更好地理解和运用这一现代化的前端开发工具。
|
1月前
|
前端开发 JavaScript
react常用的hooks有哪些?
react常用的hooks有哪些?
41 0
|
1月前
|
前端开发 JavaScript UED
使用React Hooks优化前端应用性能
本文将深入探讨如何使用React Hooks来优化前端应用的性能,重点介绍Hooks在状态管理、副作用处理和组件逻辑复用方面的应用。通过本文的指导,读者将了解到如何利用React Hooks提升前端应用的响应速度和用户体验。
|
30天前
|
存储 前端开发 JavaScript
React Hooks 的替代方案有哪些?
【5月更文挑战第28天】React Hooks 的替代方案有哪些?
28 2
|
30天前
|
前端开发 JavaScript 开发者
React Hooks 的应用场景有哪些?
【5月更文挑战第28天】React Hooks 的应用场景有哪些?
16 1
|
30天前
|
前端开发 JavaScript 开发者
React Hooks 是在 React 16.8 版本中引入的一种新功能
【5月更文挑战第28天】React Hooks 是在 React 16.8 版本中引入的一种新功能
27 1
|
1月前
|
前端开发
React Hooks - useState 的使用方法和注意事项(1),web前端开发前景
React Hooks - useState 的使用方法和注意事项(1),web前端开发前景
|
1月前
|
前端开发
探索React Hooks:一种全新的组件逻辑管理方式
React Hooks是React 16.8版本引入的一项新功能,它改变了我们编写React组件的方式。本文将从Hooks的起源讲起,逐步分析Hooks的优势,并通过具体示例展示Hooks在组件逻辑管理中的应用,旨在帮助读者更好地理解和运用React Hooks。
|
1月前
|
前端开发 API 开发者
React Hooks API:自定义Hooks的创建与使用
【4月更文挑战第25天】本文介绍了React自定义Hooks的创建与使用。自定义Hooks是提升React开发效率的关键工具。
|
1月前
|
前端开发 JavaScript
React Hooks:让你轻松掌握函数组件的状态与管理
React Hooks:让你轻松掌握函数组件的状态与管理