React 小技巧教你如何摆脱hooks依赖烦恼
程序员文章站
2022-06-27 10:34:49
react项目中,很常见的一个场景:const [watchvalue, setwatchvalue] = usestate('');const [othervalue1, setothervalue...
react
项目中,很常见的一个场景:
const [watchvalue, setwatchvalue] = usestate(''); const [othervalue1, setothervalue1] = usestate(''); const [othervalue2, setothervalue2] = usestate(''); useeffect(() => { dosomething(othervalue1, othervalue2); }, [watchvalue, othervalue1, othervalue2]);
我们想要watchvalue
改变的时候执行dosomething
,里面会引用其他值othervalue1
, othervalue2
。
这时有个让人烦恼的问题:
- 如果不把
othervalue1
,othervalue2
加入依赖数组的话,dosomething
里面很可能会访问到othervalue1
,othervalue2
旧的变量引用,从而发生意想不到的错误(如果安装hooks
相关eslint
的话,会提示警告)。 - 反之,如果把
othervalue1
,othervalue2
加入依赖数组的话,这两个值改变的时候dosomething
也会执行,这并不是我们想要的(我们只想引用他们的值,但不想它们触发dosomething
)。
把othervalue1
, othervalue2
变成ref
可以解决这个问题:
const [watchvalue, setwatchvalue] = usestate(''); const other1 = useref(''); const other2 = useref(''); // ref可以不加入依赖数组,因为引用不变 useeffect(() => { dosomething(other1.current, other2.current); }, [watchvalue]);
这样other1
, other2
的变量引用不会变,解决了前面的问题,但是又引入了一个新的问题:other1
, other2
的值current
改变的时候,不会触发组件重新渲染(useref的current
值改变不会触发组件渲染),从而值改变时候界面不会更新!
这就是hooks
里面的一个头疼的地方,usestate
变量会触发重新渲染、保持界面更新,但作为useeffect
的依赖时,又总会触发不想要的函数执行。useref
变量可以放心作为useeffect
依赖,但是又不会触发组件渲染,界面不更新。
如何解决?
可以将useref
和usestate
的特性结合起来,构造一个新的hooks
函数: usestateref
。
import { usestate, useref } from "react"; // 使用 useref 的引用特质, 同时保持 usestate 的响应性 type staterefobj<t> = { _state: t; value: t; }; export default function usestateref<t>( initialstate: t | (() => t) ): staterefobj<t> { // 初始化值 const [init] = usestate(() => { if (typeof initialstate === "function") { return (initialstate as () => t)(); } return initialstate; }); // 设置一个 state,用来触发组件渲染 const [, setstate] = usestate(init); // 读取value时,取到的是最新的值 // 设置value时,会触发setstate,组件渲染 const [ref] = usestate<staterefobj<t>>(() => { return { _state: init, set value(v: t) { this._state = v; setstate(v); }, get value() { return this._state; }, }; }); // 返回的是一个引用变量,整个组件生命周期之间不变 return ref; }
这样,我们就能这样用:
const watch = usestateref(''); const other1 = usestateref(''); const other2 = usestateref(''); // 这样改变值:watch.value = "new"; useeffect(() => { dosomething(other1.value, other2.value); // 其实现在这三个值都是引用变量,整个组件生命周期之间不变,完全可以不用加入依赖数组 // 但是react hooks的eslint插件只能识别useref作为引用,不加人会警告,为了变量引用安全还是加入 }, [watch.value, other1, other2]);
这样,watch, other1
,other2
有useref
的引用特性,不会触发dosomething
不必要的执行。又有了usestate
的响应特性,改变.value
的时候会触发组件渲染和界面更新。
我们想要变量改变触发dosomething
的时候,就把watch.value
加入依赖数组。我们只想引用值而不想其触发dosomething
的时候,就把变量本身加入数组。
以上就是react 小技巧教你如何摆脱hooks依赖烦恼的详细内容,更多关于react hooks依赖的资料请关注其它相关文章!