我想仅在 customFunction
完成设置 customEffect
状态时运行 isReady
。并且 customFunction
应该只运行一次,无论 isReady
是设置为 false
还是 true
,只要它在设置后运行即可。
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 完成之前运行。
答案 0 :(得分:1)
由于您希望在设置 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</>
);
}
答案 1 :(得分:1)
将初始值设置为 null
并按照 Kevin 的建议使用单独的 useEffect
(仅不检查 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</>
)
}
答案 2 :(得分:0)
我不确定我是否理解正确,但这就是我使用单独的 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</>
)
}
答案 3 :(得分:0)
您是否尝试过使用此软件包,isMounted?
我在我的项目中使用了它。
import React, { useState, useEffect } from 'react';
import useIsMounted from 'ismounted';
import myService from './myService';
import Loading from './Loading';
import ResultsView from './ResultsView';
const MySecureComponent = () => {
const isMounted = useIsMounted();
const [results, setResults] = useState(null);
useEffect(() => {
myService.getResults().then(val => {
if (isMounted.current) {
setResults(val);
}
});
}, [myService.getResults]);
return results ? <ResultsView results={results} /> : <Loading />;
};
export default MySecureComponent;