Open cisen opened 5 years ago
模拟shouldComponentUpdate
const areEqual = (prevProps, nextProps) => {
// 返回结果和shouldComponentUpdate正好相反
// 访问不了state
};
React.memo(Foo, areEqual);
模拟componentDidMount
useEffect(() => {
// 这里在mount时执行一次
}, []);
模拟componentDidUpdate
const mounted = useRef();
useEffect(() => {
if (!mounted.current) {
mounted.current = true;
} else {
// 这里只在update是执行
}
});
模拟componentDidUnmount
useEffect(() => {
// 这里在mount时执行一次
return () => {
// 这里在unmount时执行一次
}
}, []);
模拟isMounted
// 使用
onst isMounted = useIsMounted();
// 模拟
const [isMount, setIsMount] = useState(false);
useEffect(() => {
if (!isMount) {
setIsMount(true);
}
return () => setIsMount(false);
}, []);
return isMount;
模拟Force Update
// 使用
const update = useUpdate();
// 模拟,注意:setXXX === useState(0)[1],这里相当于强制调用setXXX来重新render
const useUpdate = () => useState(0)[1];
介绍
https://github.com/cisen/blog/issues/174
思考
hooks使用规则
API
useState
想定于初始化一个值和它的getter
传入函数
initialState参数是初始渲染期间使用的状态。 在随后的渲染中,它被忽略了。 如果初始状态是昂贵计算的结果,则可以改为提供函数,该函数仅在初始渲染时执行
useEffect
useEffect 就是告诉组件在“渲染完”之后做点什么事,是异步的 第二个可选参数,只有同一 useEffect 的两次调用第二个参数不同时,第一个函数参数才会被调用
useContext
接受由最近的context provider使用React.createContext生成的Context作为参数,返回Context的值给用户使用。当provider更新的时候,这个hook会触发一次render并返回最新的context值
useReducer
这个类似useState,只是它能接受一个reducer来派发不同action生成不同的state。官方说明挺多的,建议看看。
useCallback
上面的useCallback会将我们传递给它的函数fnB返回,并且将这个结果缓存;当依赖a变更时,会返回新的函数。既然返回的是函数,我们无法很好的判断返回的函数是否变更,所以我们可以借助ES6新增的数据类型Set来判断,具体如下:
const set = new Set();
export default function Callback() { const [count, setCount] = useState(1); const [val, setVal] = useState('');
}
不仅是上面的例子,所有依赖本地状态或props来创建函数,需要使用到缓存函数的地方,都是useCallback的应用场景。
useMemo
重要你只能用useMemo作为性能优化,不能作为语法支持。因为未来react可能会忘记以前记忆的值,并在下一次render重新计算它。所以确保代码在没有useMemo支持下也能正确运行!
这里创建了两个state,然后通过expensive函数,执行一次昂贵的计算,拿到count对应的某个值。我们可以看到:无论是修改count还是val,由于组件的重新渲染,都会触发expensive的执行(能够在控制台看到,即使修改val,也会打印);但是这里的昂贵计算只依赖于count的值,在val修改的时候,是没有必要再次计算的。在这种情况下,我们就可以使用useMemo,只在count的值修改时,执行expensive计算:
上面我们可以看到,使用useMemo来执行昂贵的计算,然后将计算值返回,并且将count作为依赖值传递进去。这样,就只会在count改变的时候触发expensive执行,在修改val的时候,返回上一次缓存的值。
useRef
可以使用
useRef
来保存全局变量,只有初始化依赖mount生命周期,其他所有改动都由自己控制 useRef返回一个可变的ref对象,其.current属性被初始化为传递的参数(initialValue)。返回的对象将持续整个组件的生命周期。吧useRef放到useEffect里面,可以保持上一次的dom用法
保存dom
保存事件程序
存储以前的值
useImperativeHandle
useImperativeHandle应该跟forwardRef一起使用
useLayoutEffect
useDebugValue
不推荐在代码中使用