React Hooks

2022-03-04  本文已影响0人  一个记事本

Hoooks:

. Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
. 使用 Hook 其中一个目的就是要解决 class 中生命周期函数经常包含不相关的逻辑,但又把相关逻辑分离到了几个不同方法中的问题。

1、useState:

const [count, setCount] = useState(0)

count:变更名
setCount:更新方法:

setCount(count + 1) 
 //或者
setState(item => {
  return {item + 1};
});
惰性初始 state
    const [state, setState] = useState(() => {
        // 组件的初始渲染中起作用,有些需求要在初始时做复杂的计算做为state初始值。
        return count + counts + 10;
    });
问:

React 怎么知道 useState 对应的是哪个组件,因为我们并没有传递 this 给 React。(更新数据时都会调用一次组件,也就是会再执行一次函数组件,那么count值为什么可以保存上次的呢?)

解:

React 保持对当先渲染中的组件的追踪,每个组件内部都有一个「记忆单元格」列表。它们只不过是我们用来存储一些数据的 JavaScript 对象。当你用 useState() 调用一个 Hook 的时候,它会读取当前的单元格(或在首次渲染时将其初始化),然后把【指针】移动到下一个。这就是多个 useState() 调用会得到各自独立的本地 state 的原因。

个人理解:闭包(因为组件都被「记忆单元格」【指针】引入了)。

函数组件也是一个闭包,其中定义的count变量做为闭包私有变量会被useState中强引用,而等到数据更新再次执行函数组件时,会把强引用变量值给到相同变量名。

2、useEffect :

useEffect( () => {} )
说明:

1.useEffect会在第一次渲染及【每次更新】后延迟执行
2.useEffect可当做componentDidMount(挂载完成),componentDidUpdate(更新完成) 和 componentWillUnmount(组件卸载前) 这三个生命周期函数的组合。
3.与 componentDidMount 或 componentDidUpdate 不同,使用 useEffect 调度的 effect 不会阻塞浏览器更新屏幕,这让你的应用看起来响应更快。
4.useEffect的参数为一个函数(异步),React 会保存这个函数(我们将它称之为 “effect”),并且在执行 DOM 更新之后调用它(闭包机制)。
## 需要清除的 effect:componentWillUnmount(组件卸载前)在哪做? ##
为保持代码的紧密性,所以 useEffect 的设计是在同一个地方执行。如果你的 effect 返回一个函数,React 将会在执行清除操作时调用它:

useEffect( () => { return () => {//这里做需要清除的事件} } )
Effect性能优化:

在某些情况下,每次渲染后都执行清理或者执行 effect 可能会导致性能问题。
在 class 组件中

在 class 组件中,我们可以通过在 componentDidUpdate 中添加对 prevProps 或 prevState 的比较逻辑解决:
          componentDidUpdate(prevProps, prevState) {
                if (prevState.count !== this.state.count) {  //如果state中count值有变化,那么就更新document.title
                        document.title = `You clicked ${this.state.count} times`;
                }
            }

在函数组件中

在函数组件中,设置useEffect 的第二个可选参数即可解决:
                useEffect(() => {
                    document.title = `You clicked ${count} times`;
                }, [count]); // 仅在 count 更改时更新document.title
useEffect(()=>{
        console.log('useEffect第二个参数为[]时,当前函数仅在组件挂载和卸载时执行');
        return () => {
            console.log('我要被销毁了');
        }
    },[]) // useEffect第二个参数为[]时,当前函数仅在组件挂载和卸载时执行

3、createContext(挂载) & useContext(解析)

useContext类似props

1、创建一个 React 的 上下文 createContext
const MyContext = React.createContext(defaultValue) //defaultValue 是传入的默认值。
//如果匹配不到最新的 Provider 则会使用默认值,默认值一般只有在对组件进行单元测试(组件并未嵌入到父组件中)的时候,比较有用。

2、父组件引入了实例,并且通过 MyContext.Provider 将子组件包装,并且通过 Provider的value 将父组件方法提供出去。
<MyContext.Provider value={{ setStep }}>
     <子组件 />
</MyContext.Provider>

3、子组件通过useContext解析父组件提供的方法,从而达到子组件中可调用及修改父组件的方法和state。
const { setStep } = useContext(MyContext);

useReducer:

1、useState 的替代方案。
2、useReducer 会比 useState 更适用,例如 state 逻辑较复杂且包含多个子值,或者下一个 state 依赖于之前的 state 等。并且,使用 useReducer 还能给那些会触发深更新的组件做性能优化,因为[你可以向子组件传递 dispatch 而不是回调函数

Hook 规则:

1. 只在最顶层使用 Hook,不要在循环,条件或嵌套函数中调用 Hook
2. 只在 React 的函数组件中调用 Hook,不要在普通的 JavaScript 函数中调用 Hook。
3. Hook 规则插件来强制执行上两条规则:

npm install eslint-plugin-react-hooks --save-dev 

// 你的 ESLint 配置
{
  "plugins": [
    // ...
    "react-hooks"
  ],
  "rules": {
    // ...
    "react-hooks/rules-of-hooks": "error", // 检查 Hook 的规则
    "react-hooks/exhaustive-deps": "warn" // 检查 effect 的依赖
  }
}
上一篇下一篇

猜你喜欢

热点阅读