问题
I have a useEffect in my Routes in App.js
<Switch>
<Route exact path={['/en', '/fr']} component={HomePage} />
<Route path={['/en/*', '/fr/*']}>
<Route path="/:lang/*" component={DefaultLanguage} />
in the same file(App.js) we have the component like so (using react-localize-redux):
const DefaultLanguage = withLocalize(
({ activeLanguage, setActiveLanguage, ...props }) => {
useEffect(() => {
console.log('setting active language');
setActiveLanguage(props.match.params.lang);
}, []);
return <></>;
}
);
The problem is every link i click runs setActiveLanguage even though i put []
to make it only run on first render (because that's the only time I care about setting language from URL) I've had this issue in other parts of the app as well. From my understanding useEffect shouldn't run everytime the component is mounted unless its dependancies change, but it seems I'm missing a detail.
回答1:
You are correct that passing an empty array to useEffect
will stop it from running on subsequent renders, but that will not stop it from running if the component is unmounted and then mounted again.
My guess is that by clicking on your links you are actually un-mounting and then re-mounting your DefaultLanguage
component.
You could test this by returning a cleanup function from your useEffect
hook.
For example,
useEffect(() => {
console.log('setting active language');
setActiveLanguage(props.match.params.lang);
return () => console.log('Unmounting');
}, []);
If you are seeing that log, then you've found your problem.
A quick and dirty solution could be to check and see if the language has changed, and if so set it. That won't address the potentially unnecessary mount/unmount but will at least avoid setting the language again.
useEffect(() => {
if (activeLanguage !== props.match.params.lang) {
console.log('setting active language');
setActiveLanguage(props.match.params.lang);
}
}, []);
来源:https://stackoverflow.com/questions/56193923/reactjs-why-useeffect-sometimes-runs-on-every-mount-render-instead-of-just-first