|
|
|
|
|
by mattkrick
2470 days ago
|
|
Hooks are absolutely fantastic. However, there are still a few pain points: - useState with an array is bad news if more than 1 component is consuming or setting the state.The clunky alternative is to keep it in a ref & call a forceUpdate whenever you would normally call your setter - useCallback doesn't scratch the itch for things like document event listeners since everything inside the callback will be stale. The clunky alternative is a custom useEventCallback that keeps your callback function in a ref. (and that might not work in the upcoming sync mode) - linter rules can be too strict & the --fix flag can actually cause a break in your app by adding things to the dependency list. Sometimes a useEffect depends on the current value of a ref, but linter says that's a no-no. 2 useCallbacks can be co-dependent, but there's no way to write that co-dependence in the dependency list. Sometimes I want to return null before a hook. The clunky alternative for all these is a bunch of eslint-ignore comments. |
|
It sounds like you might be setting state by modifying the array and then calling the setter. This won't work:
Instead, you have to update the array immutably, like setArray([...array, thing]).> useCallback for event listeners
useEffect is usually the right place to set up event listeners (and has a built-in way of cleaning them up, by returning a cleanup function).
> Sometimes I want to return null before a hook.
Hooks pretty much have to be at the very top of the component, and eslint-ignore'ing those errors will probably cause weird issues later. Better to think about another way to solve the problem that doesn't involve returning early.
An issue I ran into recently: I had a modal Edit dialog with some form state that was initialized with the current values of the thing I wanted to edit. If that modal was always mounted and merely shown/hidden (<Modal isOpen={itemToEdit}/>), the state would be initialized once and wouldn't update when I changed the item-to-be-edited. The fix was to unmount the dialog, and only mount it when there was an item to edit, {itemToEdit && <Modal isOpen={true}/>}