关于javascript:React Hook-在componentDidMount处触发多个” useEffect”

React Hook - multiple “useEffect” fires at componentDidMount

我正在使用多个useEffect挂钩来执行componentDidMountcomponentDidUpdate功能,但是,看起来像在加载组件时,我的所有useEffect最初都会触发...

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
const testComp = () => {
   const stateUserId = useSelector(state => { return state.userId; });
   const [userId, setUserId] = useState(stateUserId);
   const [active, setActive] = useState(false);
   const [accountId, setAccountId] = useState();
   
   useEffect(() => {
      console.log('component did mount...');
   }, [userId]);
   
   useEffect(() => {
      console.log('should trigger when userId changes...');
   }, [userId]);

   useEffect(() => {
      console.log('should trigger when active changes...');
   }, [active]);
   
   useEffect(() => {
      console.log('should trigger when accountId changes...');
   }, [accounted]);
 
   return (...</div);
}

安装我的组件时,我在那里看到所有那些控制台日志

1
2
3
4
component did mount...
should trigger when userId changes...
should trigger when active changes...
should trigger when accountId changes...

当依存关系仅发生变化时,我怎么只让我的第一个useEffect触发,而其他三个触发?


useEffect不能直接替换componentDidMountcomponentDidUpdate。效果将在每次渲染后运行,这就是为什么您看到所有这些控制台日志的原因。根据React文档,useEffect的第二个参数表示

you can choose to fire them (effects) only when certain values have changed.

在初始渲染之后,如果再次渲染该组件,则仅效果观察会触发相应的值更改。

一种实现所需目标的方法是创建其他变量来承载初始值,并在需要时在useEffect中进行比较。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
const testComp = () => {
  const initUserId =  useSelector(state => { return state.userId; });
  const stateUserId = initUserId;
   const [userId, setUserId] = useState(stateUserId);
   
   useEffect(() => {
      console.log('component did mount...');
   }, [userId]);
   
   useEffect(() => {
      if (userId !== initUserId) {
        console.log('should trigger when userId changes...');
      }
     
   }, [userId]);
 
   return ...
}


您可以使用自定义useEffect:

1
2
3
4
5
6
7
8
const useCustomEffect = (func, deps) => {
    const didMount = useRef(false);

    useEffect(() => {
        if (didMount.current) func();
        else didMount.current = true;
    }, deps);
}

并在您的组件中使用它:

1
2
3
useCustomEffect(() => {
      console.log('trigger when userId changes...');
}, [userId]);

任何useEffect挂钩将始终在组件安装时以及其依赖项数组中的某些变量发生更改时触发。如果要仅在变量更改时执行操作,则必须先检查传入的值并进行所需的验证。
同样,您的第一个useEffect必须具有一个空的依赖项数组才能在组件装入时立即将其触发,因为照原样,当userId更改时也会调用它。