I want to prevent the triggering of a useEffect hook which contains a useState value in the dependency array. To make it clear, look at the example.
In the initialization process a form will set some values therefore I defined a flag to prevent the other effect to execute before it is fully initialized, but I also don't want to trigger the second effect when the initialization flag state is changed.
Can I somehow prevent the tracking of this isInitialization
state? I couldn't find a thread which is solves my problem. Would you maybe so kind to link the threads which are related to that? Thanks in advance.
export function SomeComponent(props) {
const [form] = useForm();
const [settings, setSettings] = useState(props.initialSettings);
const [isInitialization, setIsInitialization] = useState(true);
/**
* Updates the form settings state, just for initialization
*/
useEffect(() => {
if (isInitialization) {
form.setFieldsValue({
...settings,
});
setIsInitialization(false); // <-- This should not trigger any useEffect
}
}, [settings, form, isInitialization]);
useEffect(() => {
if (props.settingsChanges && !isInitialization) {
props.settingsChanges(settings, isValid && hasRequiredFields);
}
}, [settings, props, isInitialization]);
}
Try to delete isInitialization
from dependency array.
useEffect(() => {
if (isInitialization) {
form.setFieldsValue({
...settings,
});
setIsInitialization(false); // <-- This should not trigger any useEffect
}
}, [settings, form]);
If you want to run an effect and clean it up only once (on mount and unmount), you can pass an empty array ([]) as a second argument. This tells React that your effect doesn't depend on any values from props or state, so it never needs to re-run. This isn't handled as a special case — it follows directly from how the dependencies array always works.
UPDATE:
Building your own Hooks lets you extract component logic into reusable functions.
If it is common logic, then you can create custom hooks and share across components.
«useMyCustomHook.jsx» file:
import { useEffect } from 'react';
export default function useMyCustomHook(str) {
useEffect(() => {
console.log(`title`, title);
});
}
and then use it in component:
function fooFunction(props) {
const [firstName, setFirstName] = useState('');
useMyCustomHook(`This is ${firstName}`);
return (
<div>The firstname is {firstName}</div>
);
}
Special thanks to @Martin. This is solution does not actually solve the problem of skip the useEffect triggering, but helped me to refactor my code even more. Maybe this is not related, but I still wanted to share my outcome with you:
In the end it looks similar like this. The initialization flag is not needed anymore, because the custom hook does it already:
const useAntForm = (initalData) => {
const [form] = useForm();
form.setFieldsValue({
...initalData,
});
return form;
};
export function SomeComponent({
settingsChanges,
initialSettings,
}: SettingsProps) {
const form = useAntForm(initialSettings);
const [settings, setSettings] = useState(initialSettings);
const [isValid, setIsValid] = useState(false);
.
.
.
}
According to https://reactjs.org/docs/hooks-rules.html it is possible to leave out dependencies in the useEffect
hook when they shouldn't trigger rerendering. Usually when leaving out dependencies it says
React Hook useEffect has a missing dependency: 'someDependency'. Either include it or remove the dependency array.
In order to fix this you just need to add https://www.npmjs.com/package/eslint-plugin-react-hooks to your eslint config which is mostly located in the package.json
file
My config now looks like:
package.json
{
...
"eslintConfig": {
"extends": [
"react-app",
"react-app/jest"
],
"plugins": [
"react-hooks" // <-- Added this
]
},
...
}
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.