React 理念:UI = f(data)
纯函数在加载不同数据后产生了不同的 UI
useState
|
|
随着组件更新 render,useState 会产生多个 n,但每次 get 的 n 是最新的 n
组件每次重新渲染,组件里的函数都会重新执行,
对应的所有 state 都会出现重复分身
如果你不希望出现重复分身的变量
可以用 useRef/useContext 等
如:
|
|
useState 不能局部更新
useState 如果数据地址没变那么 react 就不会重新 render 更新
如果 useState 的对象生成复杂建议把初始值写成一个匿名函数,不然每次重新渲染时都要做多余的计算开销
useState(() => ({ name: ’neo' }))
setState 会合并多个同级别的对 n 的操作,
如:
|
|
|
|
所以 setState 建议传入一个匿名函数方法,可以防止上面的合并操作,也可以防止代码出现过时的闭包,
比如: setN(i => i + 1)
useReducer
useReducer 是一个把对 state 的所有操作都聚拢在内的 useState
用来践行 flux 思想,具体过程如下:
1.创建初始值 initialState
2.创建所有操作 reducer(state, action)
3.传给 useReducer,得到读和写 api
4.调用时写 ({ type: ‘操作类型' })
redux 主要做到了:
1.集中管理全局状态和对状态的操作
2.提供所有子组件可以在上下文中读写全局状态
useContext
现在可以用 useState/useReducer 和 useContext 来代替 redux
|
|
|
|
useEffect
useEffect(定义:执行在 render 后的副作用)
依赖参数中数组里的值的变化来决定是否要执行函数
App() -> 执行 -> VDOM(VNode)
-> DOM ->useLayoutEffect -> 浏览器改变外观 -> useEffect
useEffect 在浏览器渲染完成后执行
useLayoutEffect 在浏览器渲染前执行
useLayoutEffect 总是比 useEffect 先执行,
useLayoutEffect 里的任务最好是影响了 useEffect
useMemo && useCallBack
useMemo 可以实现函数的重用,防止在多次 render 的时候做不必要的重复创建和执行函数
第一个参数是 ()=>value
第二个参数是依赖 [m,n]
只有当依赖不变时,才会计算新的 value,
如果依赖不变,那么就重用之前的 value
(vue2 computed?)
如果 value 是一个函数,那么要写成
()=> ((x)=> console.log(x))
可以用 useCallBack 简化
useCallback(x=>log(x), [m]) 等价于
useMemo(() => x => log(x), [m])
useRef
useRef 的目的:在组件不断 render 时,需要一个值保持不变,比如可以累积计算之类的
useRef 原理:用对象的形式来存变量,在对象里可以做到改变对象的值,而不变对象的地址
为了保证值不变,所以使用引用
初始化:const count = useRef(0)
读取:count.current
汇总
App() 重复 rendering…
每次变 useState/useRender,setN 会触发重新 render
有条件时变 useMemo/useCallBack,防止函数有多余的 render
不变 useRef ,改变值不会触发重新 render
(vue3 ref 值有变化会自动 render)
React.forwardRef
我们可以给一个函数组件一个 ref 来方便引用一个组件(就可以不用 getElementById 了),
但是函数式组件不能直接用 useRef 产生的 ref(class 组件可以直接用),因为函数式组件的 props 里不包含 ref
此时需要用 React.forwardRef 包裹一下函数组件来获得 ref
|
|
useImpreativeHandle
useImpreativeHandle 可以以 ref 为参数返回一个自定义的 ref 对象,封装 ref 对象,隐藏一些属性。
自定义 hooks
自定义 hooks 是 对已有的基础 react hooks 互相组合的封装
记录日常遇到的问题: 1.表单像 input 是用 useState 还是 useRef,有什么区别?
如果将表单值保持在状态(即受控组件),一个好处是可以在更改时立即访问值,例如,如果你希望在用户在输入框中键入某些内容时禁用某些按钮。
如果采用 ref 方法(也称为非受控组件),一个好处是不必每次用户键入时都重新呈现组件(因为调用 state update 会重新呈现)