这是 React 源码解析系列第一篇文章,系列文章基于 v16.8.6
版本。
示例代码地址 https://github.com/lxfriday/files-store/blob/master/react-source/demo1.js
Hooks 介绍
Hooks 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。
Hooks 非常简单,比如 useState 可以在 function component 中获取、设置 state 等等。
- 完全可选的。 你无需重写任何已有代码就可以在一些组件中尝试 Hook。但是如果你不想,你不必现在就去学习或使用 Hook;
- 100% 向后兼容的。 Hook 不包含任何破坏性改动;
- 现在可用, Hooks 已发布于 v16.8.0。
Hooks 为已知的 React 概念提供了更直接的 API:props, state,context,refs 以及生命周期。
Hooks 使用规则
- 只能在函数最外层调用 Hook。不要在循环、条件判断或者子函数中调用。
- 只能在 React 的函数组件中调用 Hook。不要在其他 JavaScript 函数中调用。
有哪些 Hooks
Hooks 定义在react/packages/react/src/ReactHooks.js
,在 react/packages/react/src/React.js
中查看导出的所有 Hooks。
- useState
- useEffect
- useRef
- useReducer
- useContext
- useMemo
- useCallback
- useImperativeHandle
- useDebugValue
- useLayoutEffect
useState
用法
useState
对应 class component setState
const [state, setState] = useState(initialState);
// or
const [state, setState] = useState(() => initialState);
与 class 组件中的 setState 方法不同,useState 不会自动合并更新对象。你可以用函数式的 setState 结合展开运算符来达到合并更新对象的效果。
setState(prevState => {
// 也可以使用 Object.assign
return {
...prevState, ...updatedValues};
});
惰性初始 state
initialState
参数只会在组件的初始渲染中起作用,后续渲染时会被忽略。 如果初始 state 需要通过复杂计算获得,则可以传入一个函数,在函数中计算并返回初始的 state,此函数只在初始渲染时被调用。
const [count , setCount] = useState(() => {
console.log('useState function');
return 1;
});
useState function
只在最开始打印一次。
运行特征
- object state 在 setState 时,先对象展开进行合并再 return,每次返回一个新 object 组件都会重新 render,因为前后的 state 引用是不同的;
- 如果是按引用 setState,则在初始情况下就不会 rerender 了,而先返回对象展开合并的新对象再设置引用的 state,则会在第一次设置引用时 rerender,之后就不会了。
测试代码
function App() {
// 使用 object state
const [state , setState] = useState({
name: 'lxfriday',
age: 10,
school: