Reputation: 91
I'm experiencing something similar to this: Should Custom React Hooks Cause Re-Renders of Dependent Components?
So, I have something like this:
const ComponentA = props => {
const returnedValue = useMyHook();
}
And I know for a fact that returnedValue
is not changing (prev. returnedValue
is ===
to the re-rendered returnedValue
), but the logic inside of the useMyHook
does cause internal re-renders and as a result, I get a re-render in the ComponentA
as well.
I do realize that this is intentional behavior, but what are my best options here? I have full control over useMyHook
and returnedValue
. I tried everything as I see it, caching(with useMemo
and useCallback
) inside of useMyHook
on returned value etc.
Update
Just to be more clear about what I'm trying to achieve:
I want to use internal useState
/ useEffect
etc inside of useMyHook
and not cause re-render in the ComponentA
Upvotes: 8
Views: 15653
Reputation: 11
import React, { useState, useEffect } from "react";
let times = -1;
export default function useCounter(cb = () => {}) {
useEffect(() => {
if (times == 1) {
console.log(times);
cb();
}
times = times + 1;
});
return null;
}
The above snioppet could be a simple and tricky example to prevent unwanted code execution while using custom hooks, but preventing re-rendering is not possible.
Upvotes: 0
Reputation: 139
If you intend to modularize logic, options here would be to use a global state solution (context will do, you can useMemo() on returned value) or a separate component which will return null and from which you'll setState() state on upper level. A combination of them will also do of course, and I think it can be a bit cleaner then shenanigans with useRef.
Upvotes: 1
Reputation: 602
there is no way to avoid rerendering, each state change causes the component to be updated, to avoid rerendering I recommend that you generate an auxiliary component that receives said rerendering but this must be as a child of the component
Upvotes: -1
Reputation: 13043
I want to use internal useState / useEffect etc inside of useMyHook and not cause re-render in the ComponentA
If you want to avoid the renders triggered by useState()
or useEffect()
then they are not the right tools.
If you need to hold some mutable state without triggering renders then consider using useRef()
instead.
This question has a nice comparison of the differences between useState()
and useRef()
.
Here is a simple example:
const ComponentState = () => {
const [value, setValue] = useState(0);
return (<>
<button onClick={() => {
// Will trigger render
setValue(Math.random());
}></button>
</>);
}
const ComponentRef = () => {
const valueRef = useRef(0);
return (<>
<button onClick={() => {
// Will not trigger render
valueRef.current = Math.random();
}></button>
</>);
}
Upvotes: 4
Reputation: 2768
Try to find out the reason of re-rendering in your hook, probably caused due to a state update. If it is due to updation of states in useEffect then give the states and values as dependency. If your states are updating in a function, do try to call the function in order to invoke.
If these doesn't work, try to use ref. useRef hook can be used to prevent such re-renders as it will provide you with .current values.
It would be better if you remove your useEffect dependencies one by one so that you can know what dependency is causing the error and create a ref for the same.
You can share a codesandbox and I would be happy to help you out with it.
Upvotes: 2