如何在 useEffect 中设置状态完成后调用函数?
我希望仅当
customEffect
完成设置
isReady
状态时才运行
customFunction
。并且,无论
isReady
设置为
false
还是
true
,只要在设置后运行,
customFunction
都应只运行一次。
import customFunction from 'myFile';
export const smallComponent = () => {
const [isReady, setIsReady] = useState(false);
useEffect(() => {
const customEffect = async () => {
try {
const response = await get(
`some-api.com`,
);
return setIsReady(response); // response can be true or false
} catch {
return null;
}
};
customEffect();
customFunction();
}, []);
return (
<>Hello World</>
)
}
我尝试添加 isReady 作为第二个 useEffect 参数,但我的 customFunction 在 customEffect 完成之前运行,然后在设置 isReady 之后再次运行。
还尝试使用单独的 useEffect,但似乎仍然在 customEffect 完成之前运行。
将初始值设置为
null
并使用单独的
useEffect
,正如 Kevin 所建议的(仅不检查
isReady
true/false)。
在这种情况下,
setIsReady
会将
isReady
从 null 更改为 true/false,并且将调用第二个
useEffect
。
import customFunction from 'myFile';
export const smallComponent = () => {
const [isReady, setIsReady] = useState(null);
useEffect(() => {
const customEffect = async () => {
try {
const response = await get(
`some-api.com`,
);
return setIsReady(response);
} catch {
return null;
}
};
customEffect();
}, []);
useEffect(() => {
if (null === isReady) {
return;
}
customFunction();
}, [isReady]);
return (
<>Hello World</>
)
}
由于您想要提示效果在
设置
isReady
状态后
运行,并且
isReady
的值无关紧要,因此您可以使用第二个状态值来指示第一个效果和状态更新已完成。
这将触发第二个效果以调用
customFunction
,但您不希望您的组件保持此状态,因为从现在起,任何时候组件重新渲染,条件仍将得到满足。您需要第三个“状态”来指示第二个效果已触发。在这里,您可以使用 React ref 来指示这一点。
export const smallComponent = () => {
const [readySet, setReadySet] = useState(false);
const [isReady, setIsReady] = useState(false);
const customFunctionRunRef = useRef(false);
useEffect(() => {
const customEffect = async () => {
try {
const response = await get(
`some-api.com`,
);
setReadySet(true); // to trigger second effect callback
return setIsReady(response); // response can be true or false
} catch {
return null;
}
};
customEffect();
}, []);
useEffect(() => {
if (readySet && !customFunctionRunRef.current) {
// won't run before readySet is true
// won't run after customFunctionRunRef true
customFunction();
customFunctionRunRef.current = true;
}
}, [readySet]);
return (
<>Hello World</>
);
}
从 @p1uton 借来的更好的解决方案。使用 null
isReady
状态来指示
customFunction
不应调用,并使用 ref 来阻止其在之后被调用。
export const smallComponent = () => {
const [isReady, setIsReady] = useState(null);
const customFunctionRunRef = useRef(false);
useEffect(() => {
const customEffect = async () => {
try {
const response = await get(
`some-api.com`,
);
return setIsReady(response); // response can be true or false
} catch {
return null;
}
};
customEffect();
}, []);
useEffect(() => {
if (isReady !== null && !customFunctionRunRef.current) {
// won't run before isReady is non-null
// won't run after customFunctionRunRef true
customFunction();
customFunctionRunRef.current = true;
}
}, [isReady]);
return (
<>Hello World</>
);
}
我不确定我是否理解正确,但这就是我使用单独的
useEffect
的方式。
import customFunction from 'myFile';
export const smallComponent = () => {
const [isReady, setIsReady] = useState(false);
useEffect(() => {
const customEffect = async () => {
try {
const response = await get(
`some-api.com`,
);
return setIsReady(response);
} catch {
return null;
}
};
customEffect();
}, []);
useEffect(() => {
if (!isReady) {
return;
}
customFunction();
}, [isReady]);
return (
<>Hello World</>
)
}