Suppose I have the following component:
function Counter({onCountChange}) {
const [count, setCount] = useState(0);
// ...suppose we have somewhere else also using the count variable
useEffect(() => {onCountChange(count)}, [count, onCountChange]);
return (
<div className="Counter">
<button onClick={() => setCount(count + 1)}>Count+</button>
<button onClick={() => setCount(count - 1)}>Count-</button>
</div>
);
}
So it would cause the circular triggering issue if we directly pass a function in, I see one way to solve this issue is to use useCallback in the parent:
const handleCountChange = useCallback(() => {...}, [dependency])
This solution introduces more complexity to the parent component.
Another solution is to let the event triggering not depend on the onCountChange:
useEffect(() => {onCountChange(count)}, [count]);
But this solution will not handle the change of the prop onCountChange, if the parent component changes the prop, it will still use the old value (I think).
We can also manually trigger the event without the useEffect:
<button onClick={() => {setCount(count + 1); onCountChange(count + 1)}}>Count+</button>
<button onClick={() => {setCount(count - 1); onCountChange(count - 1)}}>Count-</button>
Sorry for giving so many backgrounds, I just want to make the question clear enough.
So my question is, what is the best practice to trigger an event in a reusable component? Especially if we have multiple places to trigger in the component? Is the manually triggering the best practice? Or is there something that allows us to use the useEffect but neither introduces more complexity nor loses the ability to track the changes of the event function?
Disclaimer: I am not good at React at all, so I might miss something obvious.
onChangeCountinside the child component instead of the parent component? I think... it is impossible, right?