4 ms·
I like hooks but here are some uncertainties that bother me. I am quiet new to React and hooks, but I am a senior dev, so I am wondering if any of this confuses
by vvpan 6y ago
I like hooks but here are some uncertainties that bother me. I am quiet new to React and hooks, but I am a senior dev, so I am wondering if any of this confuses others.
* I sometimes have to use an empty dependency array inside useEffect to run something only when component first loads. The linter yells at me, but it makes sense. I once read an article which told to put things in functions and wrap those functions in useCallback then that'd be proper, but can't imagine the value. I think most of the internet simply does empty dependency and ignores what creators of hooks suggest.
* I want to run things before the component mounts, like API calls.
* I often want my useEffect to trigger when only one of the state variables it references is updated. Again, linter screams at me and I add an exception.
* Because useEffect triggers after component mounts, and only then, it's sometimes difficult to avoid some flicker. For example I want to do something when a components prop (say "loading") changes from "true" to "false". Loading has finished, prop has been updated, component re-rendered, and only then I can trigger what I really wanted to do on that transition. I think "componentWillReceiveProps" would have solved this, but there is no functional equivalent.
Basically if there is a person who uses "useCallback" out there "correctly" I have not met them yet. My junior subordinates misuse useEffect quiet often. I often see (and use) empty dependency arrays. I see (and use) partial dependency arrays, often adding linter exceptions. Reading articles about "proper" ways of doing it sorta makes sense but it is easy to forget what the hooks authors really meant.
I think hooks is a good feature, but the authors made too many assumptions when developing them. There is a philosophy underlying them but that philosophy is somewhat incongruent with the philosophy of "I just want to get this done". React is just one tool, I have 20 more things to do every day and understanding the full philosophy of functional dependencies and when and how to properly use "useCallback" - I just do not have time, and junior devs get confused even more.
- jakkyboi 6y agoSame with the empty array
- evan_ 6y agoI would ignore whoever told you not to use an empty array for the dependency argument. Change your linter rules. It's fine.
- brlewis 6y agoThat runs the risk of someone less experienced introducing a bug later when a new dependency is introduced. I think it's better to simply do whatever the linter says.
- evan_ 6y agoThere's also a risk that someone less experienced hits themselves in the thumb with a hammer, and then hits themselves between the eyes with the claw, and then drops the hammer on their foot.
- brlewis 6y agoAre you saying that writing code in a way that defends against future mistakes is a waste of time? It's hard to see the content of your comment through the sarcasm.
- evan_ 6y agoI do think that's important. I practice that by writing readable, well-formatted code, commenting liberally, and avoiding "too-clever" hacks. I don't think using a well-documented feature for the purpose it was intended violates any of these.
- brlewis 6y agoIs the well-documented feature the dependency array or the ability to suppress linter rules? The note at the bottom of the documentation section for the dependency array recommends using the linter rule: https://reactjs.org/docs/hooks-effect.html#tip-optimizing-performance-by-skipping-effects https://reactjs.org/docs/hooks-effect.html#tip-optimizing-pe...
- vvpan 6y agoThat's good to hear!
- sickcodebruh 6y agoIf you need an effect to run before the component draws, try `useLayoutEffect` instead of `useEffect`. https://reactjs.org/docs/hooks-reference.html#uselayouteffect https://reactjs.org/docs/hooks-reference.html#uselayouteffec...
- WesleyJohnson 6y agoHow do you handle a useEffect that relies on state, but you don't want it to run on first render? I usually have a separate state that is "firstLoad" and toggle that in the effect and exit out, then its free to run on successive invocations. But typing this out - it makes me the think the dependent state itself should be driving if it runs or not...
- sickcodebruh 6y agoI don't think there's a way around tracking that `firstLoad` value. A `ref` is probably a better choice than a separate state value because you don't need to render when the component becomes aware that you're past the first render. You could do it in a simple hook: function useFirstRenderComplete() { const renderCountRef = useRef(0); useEffect(() => { if (renderCountRef.current) { return; } renderCountRef.current += 1; }, []); return renderCountRef.current !== 0; }
- ng12 6y agoIf the dependency array lint rule is yelling at you there's a very, very good chance your component is broken. As an example I used to see class components like this all the time: class Foo extends React.Component { componentDidMount() { fetchFoo(this.props.id) .then(foo => this.setState({foo})) } render() { ... } } This component is fundamentally broken because there is no `componentDidUpdate` to re-call `fetchFoo` when `this.props.id` changes. I could easily be rendering a new id with an old id's foo. The developer is making an assumption that the initial value of `id` will never change, therefore making assumptions about how the parent component is instantiating `Foo`. Rewriting this using hooks makes this immediately obvious: const Foo = ({id}) => { const [foo, setFoo] = React.useState(null) React.useEfect(() => { fetchFoo(id).then(setFoo) , []) // Linter complains, and it should! return ... } There's nothing wrong with using the empty array as your deps so long as it's actually what you want to do. If `fetchFoo()` didn't require any arguments and we only wanted to invoke it once [] would absolutely be the right dependency array. There are few cases I can think of where disabling the linter check is correct. The most common occurence in my code is if the effect uses a value not required to be fresh: e.g. something used for an optimization.
- lumens 6y agoI found this article incredibly helpful in answering these questions: https://overreacted.io/a-complete-guide-to-useeffect/ https://overreacted.io/a-complete-guide-to-useeffect/