Javascript 反应钩-多个“;“使用效果”;在组件上开火

Javascript 反应钩-多个“;“使用效果”;在组件上开火,javascript,reactjs,react-redux,react-hooks,Javascript,Reactjs,React Redux,React Hooks,我正在使用多个useffect钩子来执行componentDidMount和componentdiddupdate功能,但是,看起来当组件加载时,我的所有useffect最初都会触发 const testComp = () => { const stateUserId = useSelector(state => { return state.userId; }); const [userId, setUserId] = useState(stateUserId);

我正在使用多个
useffect
钩子来执行
componentDidMount
componentdiddupdate
功能,但是,看起来当组件加载时,我的所有useffect最初都会触发

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);
}

我怎么能只让我的第一个
useffect
触发,而其他三个只在依赖项更改时触发?

任何
useffect
hook都将在组件装载时触发,并且在其依赖项数组中的某些变量更改时触发。如果要在变量更改时执行操作,必须首先检查传入值并执行所需的验证。
此外,您的第一个
useffect
必须有一个空的依赖项数组,以便在组件装载时触发它,因为它在用户ID更改时也会被调用。

useffect
不是
componentDidMount
componentdiddupdate
的直接替代品。效果将在每次渲染后运行,这就是您看到所有这些控制台日志的原因。根据React文档,
useffect
的第二个参数表示

只有在某些值发生更改时,才能选择激发它们(效果)

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

实现所需的一种方法是创建附加变量来承载初始值,并在需要时在
useffect
中进行比较

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>
}
const testComp=()=>{
const initUserId=useSelector(state=>{return state.userId;});
const stateUserId=initUserId;
const[userId,setUserId]=useState(stateUserId);
useffect(()=>{
log('component dod mount…');
},[userId]);
useffect(()=>{
if(userId!==initUserId){
log('userId更改时应触发…');
}
},[userId]);
返回。。。
}

您可以使用自定义useEffect:

const useCustomEffect=(func,deps)=>{
const didMount=useRef(false);
useffect(()=>{
if(didMount.current)func();
else didMount.current=true;
},副署长);
}
并在组件中使用它:


useCustomEffect(()=>{
log('userId更改时触发…');
},[userId]);

useEffect将始终至少在装载时执行,无论您在依赖项数组中传递什么。您应该创建一个自定义挂钩,如useUpdateEffect。这个问题展示了@Rodrigi Amara是如何工作的,谢谢你分享这个想法,我想知道如果是这样的话,为什么不使用useRef标志,但使用自定义钩子在同一个主组件中执行呢?另外,如何从我的主组件调用自定义钩子?自定义钩子只是函数。您可以仅为挂钩创建一个文件夹,并将其导入到组件中。或者您可以在组件内部使用useRef(就像问题中投票最多的答案一样),但您将无法在该组件外部重用此逻辑。顺便说一句,在常见问题解答中,所有效果至少运行一次,有一些参考技巧可以跳过。是的,这是可行的,但是,似乎我需要为每个应用程序中需要的每个字段创建一个局部状态变量。效用依赖list@KevDing如果您不想创建局部变量,可以使用自定义useDidMountEffect挂钩进行解答。谢谢分享,我正在查看自定义挂钩解决方案,但有点困惑。如果my deps第一次从父组件更改,如何激发func()?因为此时,
didMount.current
值仍然为false…将该值重置为true不会触发另一个useEffect,因为它是一个useRef…有没有办法从父组件将其设置为true,以便自定义挂钩可以在初始渲染时执行func(),useDidMountEffect将被触发,并将
didMount.current
更改为
true
。这就是为什么当您的dep第一次更改时(请注意,这是第二次渲染&第一次dep值更改),
didMount.current
此时已为真。因此,将执行
func()
谢谢共享,如果我的部门第一次发生更改,此时如何启动func()?因为didMount.current仍然为false…并且将该值重置为true不会触发另一个useEffect…有没有办法从我的组件将其设置为true?有关更多信息,请参阅此链接:
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>
}