I am using react-router
5.1 and react
16.10.
For a Master-Detail page, I am using useParams()
to get the id from the url to open the page for the current group. Opening happens in a useEffect()
. As a result, id
has to be given as a dependency in that effect. However, when creating a new group, when there is enough data for a group to be valid, the API sends the id
for that group and it sets the URL to /group/:id
. As a result however, the effect runs again.
function Groups(props) {
const { id } = useParams();
const history = useHistory();
const [group, setGroup] = useState(NEW_GROUP);
const getData = useCallback(async () => {
await Promise.resolve(Api.getGroups());
}, []);
const getGroup = useCallback(async group => {
history.push(`/groups/${group.id}`);
await Promise.resolve(Api.getGroup(group)).then(data => {
setGroup(data.group);
});
}, [getData, history]);
useEffect(() => {
getData();
if (id !== undefined) {
getGroup({ id });
}
}, [props.actions, id, getData, getGroup]);
// Saving data
const saveGroup = useCallback(async () => {
setSaved(SAVING);
await Promise.resolve(Api.storeGroup(group)).then(data => {
if (!group.hasOwnProperty('id')) {
history.push(`/groups/${data.id}`);
setGroup(prevGroup => ({ ...prevGroup, id: data.id }));
}
getData();
setSaved(SAVED);
}).catch(() => setSaved(FAILED));
}, [getData, group, history]);
}
How do I prevent this from happening without breaking the "rules of hooks"?
By default useEffect will trigger anytime an update happens to the React component. This means if the component receives new props from its parent component or even when you change the state locally, the effect will run again.
The useEffect Hook Usages. The callback function we pass to the useEffect hook runs the side effects. React runs it on every render of a component by default.
Anatomy of the useEffect hookThe return function is the cleanup function, or when the user leaves the page and the component will unmount. The array is the last part, and it is where you put the states that will update throughout the component's lifecycle.
'); if(count < 1) { setTimeout(() => { setCount(count + 1); }, 1000); } return ( <div>Hello World</div> ); } export default App; In this code, the code inside useEffect will only get executed once even if we change the value of the variable count multiple times.
I had the same issue, and the way I solved is by passing the id from useParams to the function and set id only in useEffect.
function Groups(props) {
const { id } = useParams();
...
useEffect(() => {
getData(id);
if (id !== undefined) {
getGroup({ id });
}
}, [id]);
...
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With