前言
hooks的作用:function组件尽量写成纯函数。若需要副作用等外部功能,则用钩子把外部代码钩进来即可
useState
1.用途
为函数组件引入状态(state)。纯函数不能有状态,所以把状态放在钩子里面。
2.语法
- i:状态的初始值
- o:[state, setState]
3.setState
setState的合并更新
假设 age 为 42
function handleClick() {
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
setAge(age + 1); // setAge(42 + 1)
}
点击后变成43,而非45
为了解决这个问题,你可以向 setAge 传递一个更新函数,而不是下一个状态。他只接受待定的 state 作为其唯一参数,并应返回下一个状态。React 将把你的更新函数放入队列中并重新渲染组件。在下一次渲染期间,React 将通过把队列中所有更新函数应用于先前的状态来计算下一个状态。
function handleClick() {
setAge(a => a + 1); // setAge(42 => 43)
setAge(a => a + 1); // setAge(43 => 44)
setAge(a => a + 1); // setAge(44 => 45)
}
setState(x) 实际上会像 setState(n => x) 一样运行,只是没有使用 n!
当state为对象时,如何正确setState
// 🚩 不要像下面这样改变一个对象:
form.firstName = 'Taylor';
// ✅ 使用新对象替换 state
setForm({
...form,
firstName: 'Taylor'
});
原因: Object.is 将会判断你的状态没有改变
state为函数时正确的存储方法
const [fn, setFn] = useState(() => someFunction);
function handleClick() {
setFn(() => someOtherFunction);
}
useContext
用途:在组件之间共享数据。它可以让您避免通过 props 层层传递数据,从而简化组件之间的通信
- 1.创建一个上下文对象export const MyContext = React.createContext({});
- 2.使用场景1:在组件中使用上下文对象,使用useContext()
import React, { useContext } from 'react';
import { MyContext } from './MyContext';
const MyComponent = () => {
const myData = useContext(MyContext);
return (
<div>
<p>{myData}</p>
</div>
);
};
export default MyComponent;
- 3.使用场景2:使用 MyContext.Provider 组件来提供要共享的数据
import React from 'react';
import { MyContext } from './MyContext';
import MyComponent from './MyComponent';
const MyParentComponent = () => {
const myData = 'Hello, world!';//需要共享的数据
return (
<MyContext.Provider value={myData}>
<MyComponent />
</MyContext.Provider>
);
};
export default MyParentComponent;
使用 MyContext.Provider 组件提供了要共享的数据,并将其存储在 myData 变量中。然后,我们将 MyComponent 组件包装在 MyContext.Provider 组件中,以便在 MyComponent 组件中访问共享的数据
Reference
https://www.ruanyifeng.com/blog/2019/09/react-hooks.html
https://zh-hans.react.dev/learn/queueing-a-series-of-state-updates