文章目录
什么是Hook
hook是可以让逆在不编写class的情况下可以使用state和其他react特性。个hook,如下
useState
useEffect
useContext
useReducer
useCallback
useMemo
useRef
useLayoutEffect
- 自定义hook
useImperativeHandle
useDebugValue
useEffect
react会等待浏览器渲染组件完成之后才会调用useEffect。即useEffect会延迟到组件渲染完成之后才调用,但会在组件下一次渲染之前执行完。
如果组件多次渲染,useEffect表现为在每次渲染完成之后执行。
条件执行useEffect
给useEffect添加第二个参数。
这个参数是指依赖数组,也就是数组内的值改变时useEffect才会执行
useEffect(
() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
},
[props.source],
);
即props.source
改变时,useEffect内的箭头函数才执行。
useEffect可以写多个
注意这里说的不是useEffect内的函数执行多次。是指可以写多个副作用函数,在函数组件内执行。情景如下:
useEffct(() => {
setTimeout(()=>{
console.log('第1个副作用函数')
},1000)
})
useEffct(() => {
setTimeout(()=>{
console.log('第2个副作用函数')
},1000)
})
useEffct(() => {
setTimeout(()=>{
console.log('第3个副作用函数')
},1000)
})
//......
这些useEffect函数都会在组件渲染完成之后被调用。
自定义hook
与普通函数的区别是,自定义hook内的值改变时会一起组件重新渲染。
相同点是,都可以实现代码逻辑的封装,实现代码复用。
函数组件与clas组件
函数组件颗粒度更小,通过使用hook可以实现更细粒度的代码复用
useState
使用示例:
const [state,setState] = useState(initalState)
useEffect函数返回一个state和一个更新state的函数。
initalState
是state的初始值,它可以是任意的数据类型:数字、字符串、对象、数组,特别的可以是函数的返回值
,如下
//let func = function(){....}
const [state, setState] = useState(() => {
const initialState = func(props);
return initialState;
});
重新命名state名称
利用ES6的数组解构可以重命名state的名称,名字只要符合命名规则即可,如下:
const [name,setName] = useState('xiezh')
甚至奇葩一些(这样子命名会被同事打死的)
const [a,b] = useSate('xiezh')
a仍然代表的是state这个对象,b也仍然是更新state的方法。
扩展开来,我们在函数组件中就可以这么写了,如下
const [count,setCount] = useState(0)
const [age,setCount] = useState(21)
const [list,setList] = useState([])
const [info,setInfo] = useState({})
//.......
我们可以通过setXxxx去修改不同的state,而其他的state保持原来的值不变。
当然因为调用了setXxxx(无论是哪一个)都会引起组件的重新渲染。
当然这是指提供了一种思路,在实际的项目中依旧可以将所有渲染数据放在一个state中(像class组件那样,不过函数组件不会将新的state和旧的state合并,而是直接替换。如果需要合并可以使用Object.assign自己合并之后再替换覆盖旧的state)。
像这样分开来写,很明显,逻辑粒度降低很多,每一个useState都可以拆分到不同的逻辑中去。
setState触发组件重新渲染
setState触发组件从新渲染的原理是新的state和旧的state不相等
。通过Object.is
方法判断是否相等。
所以得出如下结论
- 如果state为数字,newState === oldState ? ‘不更新’:‘更新’
- 如果state为字符串,newState === oldState ? ‘不更新’:‘更新’
- 如果state为数组,更新
- 如果state为对象,更新
结论可以再精炼一些
-
如果state是值类型数据,新旧state值相等? ‘不更新’ : ‘更新’
-
如果state是引用类型数据,不管新旧值是否相同,必定更新
说到这里你应该大概知道Object.is
函数的作用了,和===
差不多。具体可以这里了解:MDN-- Object.is()
函数式更新
function Counter({initialCount}) {
const [count, setCount] = useState(initialCount);
return (
<>
Count: {count}
<button onClick={() => setCount(initialCount)}>Reset</button>
<button onClick={() => setCount(prevCount => prevCount - 1)}>-</button>
<button onClick={() => setCount(prevCount => prevCount + 1)}>+</button>
</>
);
}
setState()的参数可以是一个参数为旧state的函数,函数要返回新的state
…未完成