前言
最近在工作过程中使用了React的函数式组件写法写了好几个组件,个人认为这种写法十分顺畅舒滑,因此在这记录一下函数式组件的写法和用法。
正文
- 首先则是给出一个React使用Hook的一个案例
import React, { useState } from 'react';
function Example() {
// 声明一个叫 “count” 的 state 变量。
// count为状态变量,setCount为更新该状态变量的函数
// useState的参数为该状态变量的初始值
const [count, setCount] = useState(0);
// 组件渲染内容
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}
- 如上是一个简单的计数器组件,结构简单,采用函数式组件的写法,使用了
useState
这一状态Hook。 - 全程使用function包裹组件,不会涉及到this这一概念,也就避免了this相关的一系列问题
- 下文主要是对不同的hooks作一下简单介绍
useState
- useState起到了一个创建状态变量的作用
const [state, setState] = useState(initialState);
- state指向了该状态变量,可以在后续的代码中使用state这一状态变量
- 当我们需要更新该状态变量的值时,我们就可以用setState这一个函数来更新这一状态变量
- 与Class类组件的state不同,this.setState是会自动合并更新对象的,如果要用useState起到同样的自动合并更新对象的效果的话,需要采取如下的写法
const [state, setState] = useState({});
setState(prevState => {
// 也可以使用 Object.assign
return {...prevState, ...updatedValues};
});
- 与class组件的setState相同,useState中的setState也是异步函数,因此如果我们想获取setState的回调函数时,我们在hook的写法中可以用如下写法实现。除此之外,用useEffect这一hook也能实现相同的回调效果。
const [value,setValue] =useState(0)
const add= ()=>{
new Promise((resolve)=>{
setValue((num)=>{
resolve(num+1)
return num + 1
})
}).then(res=>{
console.log(res)
...
})
}
- 另外react官方也对该setState做了一个有意思的优化,如果你更新 State Hook 后的 state 与当前的 state 相同时,React 将跳过子组件的渲染并且不会触发 effect 的执行。(React 使用 Object.is 比较算法 来比较 state。)
useEffect
useEffect(didUpdate);
- useEffect是一个用于完成副作用函数的hook,其入参为对应的副作用函数didUpdate。
- 赋值给 useEffect 的函数会在每轮组件渲染完成后执行
- 当你需要进行一些如改变 DOM、添加订阅、设置定时器、记录日志以及执行其他各种渲染过程中不允许出现的操作时,就会需要用到这个hook
- 组件卸载后应当对组件运作途中产生的一些订阅与计时器进行清除,这时候就可以用到useEffect的返回值,返回一个清除函数,该清除函数会在组件卸载之前执行。写法如下:
useEffect(() => {
const subscription = props.source.subscribe();
return () => {
// 清除订阅
subscription.unsubscribe();
};
});
- 我们也可以对副作用函数的执行增加一些依赖项,这时候我们可以对useEffect的第二个入参传入依赖项来达成目的
useEffect(
() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[props.source],
);
- 这时候只有props.source这一依赖项发生变化时才会执行副作用函数
- 如果你想要副作用函数只在挂载和卸载组件的时候执行一次(就像compnentDidMount以及componentWillUnmount一样),只需要给第二个入参传入空数组
[]
即可 - 从概念上来说它表现为:所有 effect 函数中引用的值都应该出现在依赖项数组中。