-- edit -- i created a codesandbox: https://codesandbox.io/s/xenodochial-hofstadter-d3jjo
I'm starting to scratch my head and would like some help on - I assume - a simple problem.
I have a basic App component that renders a controlled text input. Once you submit this input it creates a message on the back-end, which updates a redux store. Everything seems to be working fine on this part.
My issue is when I tried to add a useEffect
hook to reset the input value after a new message was added. I noticed that the useEffect
that relies on [messages]
is called on every render instead of just when messages
changes. The simple act of typing in the input - which causes a rerender for every character - makes the hook trigger, even though it is still the same value: an empty array.
Basically I've noticed it only works as intended if my useSelector
returns the same instance of an array. So if I were to read only state.messages.allIds
it would work since the array does not change. But simply adding a .map(x => x)
makes it return a new instance every time.
I have added react-redux's shallowEqual
to try and fix this, but to no avail, and I don't understand why it doesn't fix my problem.
const App = () => {
const [message, setMessage] = useState('');
const messages = useSelector(
(state: RootState) => (
state.messages.allIds.map((id: string) => state.messages.byId[id])
),
shallowEqual,
);
useEffect(() => {
console.log('useEffect');
}, [messages]);
// ...
return (
<form onSubmit={/* ... */}>
<input
onChange={event => setMessage(event.target.value)}
value={message}
/>
</form>
);
}
This maybe coming pretty late. But it might benefit others facing the same problem.
If you do not want the function to re-render on state change and only want to extract the value of a redux state variable, you may use useState
const state = useState();
const yourVariable = state.getState().reduxStateVariable;
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