简体   繁体   English

React Hook - 在 componentDidMount 处触发多个“useEffect”

[英]React Hook - multiple “useEffect” fires at componentDidMount

I'm using multiple useEffect hooks to perform the componentDidMount and componentDidUpdate functionalities, however, looks like when component loads, all my useEffect fires initially...我正在使用多个useEffect挂钩来执行componentDidMountcomponentDidUpdate功能,但是,看起来当组件加载时,我所有的 useEffect 最初都会触发......

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>...</div);
}

when my component mounts, I see all those console log there当我的组件安装时,我会在那里看到所有这些控制台日志

component did mount...
should trigger when userId changes...
should trigger when active changes...
should trigger when accountId changes...

How could I only let my first useEffect fires, but the other three fires when the dependency changes only?我怎么能只让我的第一个useEffect触发,而其他三个仅在依赖项更改时触发?

useEffect is not a direct replacement of componentDidMount and componentDidUpdate . useEffect不是componentDidMountcomponentDidUpdate的直接替代品。 Effect will run after each render, which is why you are seeing all those console logs.每次渲染后都会运行效果,这就是为什么您会看到所有这些控制台日志的原因。 According to the React documentation, the second parameter of useEffect means根据 React 文档, useEffect的第二个参数表示

you can choose to fire them (effects) only when certain values have changed.您可以选择仅在某些值发生更改时触发它们(效果)。

After the initial render, if the component is rendered again, only effects watch the corresponding value changes are triggered.初次渲染后,如果再次渲染组件,只会触发对应值变化的效果观察。

One way to achieve what you want is by creating additional variables to host initial values and do comparisons in the useEffect when you need to.实现您想要的一种方法是通过创建附加变量来托管初始值并在需要时在useEffect中进行比较。

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 <div>...</div>
}

Any useEffect hook will always be fired at component mount and when some of the variables in its dependency array changes.任何useEffect挂钩将始终在组件挂载时以及其依赖项数组中的某些变量发生更改时触发。 If you want to perform an action just when the variable changes you must check the incoming value first and do the required validations.如果您想在变量更改时执行操作,您必须首先检查传入值并进行所需的验证。 Also your first useEffect must have an empty dependency array to fire it just when the component mounts, because as it is it will also be called when userId changes.此外,您的第一个useEffect必须有一个空的依赖数组才能在组件安装时触发它,因为它也会在 userId 更改时被调用。

you can use custom useEffect:您可以使用自定义 useEffect:

const useCustomEffect = (func, deps) => {
    const didMount = useRef(false);

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

and use it in your component:并在您的组件中使用它:


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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM