Why you probably do not need useEffect

SdĂ­let
VloĆŸit
  • čas pƙidĂĄn 25. 05. 2023
  • 📘 T3 Stack Tutorial: 1017897100294.gumroad.com/l/j...
    đŸ€– SaaS I'm Building: www.icongeneratorai.com/
    💬 Discord: / discord
    🔔 Newsletter: newsletter.webdevcody.com/
    📁 GitHub: github.com/webdevcody
    đŸ“ș Twitch: / webdevcody
    đŸ€– Website: webdevcody.com
    🐩 Twitter: / webdevcody

Komentáƙe • 72

  • @MrPlaiedes
    @MrPlaiedes Pƙed rokem +41

    Can we just recognize trial and error and learning from your mistakes? Respect.

  • @armandsalle8447
    @armandsalle8447 Pƙed rokem +18

    The second version is what I would have done (mixed with the setState(prev => ...). The derived state is great for performances but a little bit harder to read for humans, so I think it depend on the complexity and the performances you need

  • @JThompson_VI
    @JThompson_VI Pƙed rokem +6

    It can be easy to forget, reactive state changing not only causes the the ui to update but causes the whole component to rerun. So any function or non reactive state reliant on reactive state will change.
    When I am tasked with fixing a react bug, the first thing I do is check for a useEffect.

  • @abgezuckert.
    @abgezuckert. Pƙed rokem +9

    I would consider that state is typically used for rendering stuff. And what is concretely rendered here? Either the numpad or the message. So imo the only state this component should have is the message string. Neither an isError bool where you have to derive the message from nor the pressedNumbers which are not visually represented, but rerender the component unnecessarily on every button click. So all you need is a by default null or empty message string state that gets updated by the click handler with a success or fail message after the necessary conditions can be evaluated (pressedNumber.length === 4 etc.). With !!message you render the state string, otherwise you render the numpad. Simple.

  • @pesterenan
    @pesterenan Pƙed rokem +12

    This was a great lesson on why you needed to refactor your code. You saw the problem, you've implemented your way of dealing with it, using useEffect, and then you saw how to improve on it!
    I say this is great because I'm dealing with legacy code, and the logic approaches more with not needing an useEffect, but rather a derived state that just changes inside it whenever something changes.
    It's harder to wrap your head around first, but then it just looks not only cleaner, but helps when the app gets more features for example. Nice video Cody!

  • @TheSocialDeveloper
    @TheSocialDeveloper Pƙed rokem +2

    Nice! You updated this! Couple more suggestions, although I wouldn’t go back and change anything, adding “idle” to state makes more sense for initialization. When I think of verbs ending with “-ing” I think of something happening currently, at which point you’d debounce before updating state back to “idle”. That’s really it from me. Great video!

    • @TheSocialDeveloper
      @TheSocialDeveloper Pƙed rokem

      Lines 15-18 could also be converted to a ternary since they’re pretty self explanatory

  • @xvzf115
    @xvzf115 Pƙed rokem

    That thread on your previous video was very educational. Kudos to the person that started this discussion!

  • @yzz9833
    @yzz9833 Pƙed rokem +11

    This is why I use a state manager like Zustand.

    • @tech3425
      @tech3425 Pƙed rokem +1

      What's the benefit of using zustand?

    • @orwellmushaikwa2591
      @orwellmushaikwa2591 Pƙed rokem +3

      @@tech3425 Zustand is basically a global store like redux but is much simpler to use, very little boilerplate for managing all your states. Though, in a simple example like this one which is just a single component I think zustand is overkill. State managers become really useful when you want to manage states across multiple components (Especially sibling components).

    • @enyelsequeira3619
      @enyelsequeira3619 Pƙed rokem +1

      Zustand is definitely an overkill for something simple like this

    • @yzz9833
      @yzz9833 Pƙed rokem

      @@enyelsequeira3619 certainly is not considering it is unopinionated and a store can be created in a single line.

    • @orwellmushaikwa2591
      @orwellmushaikwa2591 Pƙed rokem

      @@yzz9833 Interesting, I haven't really used it personally I've only looked into it and have seen projects at work using it. So do you use it for all cases in place of useState or useReducer?

  • @SeibertSwirl
    @SeibertSwirl Pƙed rokem +9

    Lol when you said “you should read this article” I chuckled and said “I bet Cody skimmed it at best” lol sure enough that’s what you said right after hahahahaha love you babe! You’re doing great

    • @WebDevCody
      @WebDevCody  Pƙed rokem +3

      You know me so well lol

    • @Zzyzx-
      @Zzyzx- Pƙed rokem

      Link to the article in description pls

  • @anuj7286
    @anuj7286 Pƙed rokem

    Thankyou for great explanation. Please bring more tutorials on how to prevent re rendering and slow issues?

  • @Dom-zy1qy
    @Dom-zy1qy Pƙed rokem +3

    I feel like useEffect just sounds super intuitive to use because of how we think of processes as humans. Semantically "do this as a side effect when X changes" just sounds more... "complete?". Its often times more bloated code (and sometimes leads to broken code) but for me the first thing that comes to mind when im writing code like this is: "how can i achieve X running when Y changes, kind of a "side effect of something happening", oh yeah react basically has a hook for this! "

  • @okage_
    @okage_ Pƙed rokem

    was waiting for this after i read that comment haha
    glad you made it a video and broke it down

  • @Sl1de13
    @Sl1de13 Pƙed rokem

    I would only use the state to display the end result, not store the entered numbers in it. and I would store the entered numbers with useRef so there is no re-rendering for every input. and on the last input, check if the password was entered correctly and change the final state to pass or fail

  • @UmairSadaqat
    @UmairSadaqat Pƙed rokem +1

    Great but I think is too much rendering when you are using the last approach because whenever this component is rendered is always buggy with if-else statements

  • @petermckeever2360
    @petermckeever2360 Pƙed rokem +1

    Moving to a handler instead of useEffect definitely the right call. Don't know if i would completely remove useState though

  • @dcmbassi
    @dcmbassi Pƙed rokem

    I zeroed in on that doc article as soon as it went live. I've been freeing myself from overreliance on useEffect ever since.

  • @adarsh-chakraborty
    @adarsh-chakraborty Pƙed rokem +3

    I get it, Not using useEffect is good but I would still use 3 different state variables instead of checking for state of one variable at multiple places

  • @harrisonchan2992
    @harrisonchan2992 Pƙed rokem

    What if I was using redux or zustand and wanted to do in a component if something in my store changed?

  • @julo.parapente
    @julo.parapente Pƙed 7 měsĂ­ci

    "number: string". Badass.

  • @omega_sine
    @omega_sine Pƙed rokem +2

    Would this be a valid use of useEffect:
    I wanted to extend this challenge and allow the user to type an answer using the keyboard. I believe react provides onKeyPress or something similar for key presses, but when using that it seems that the user must be focused on the specific element. I wanted to be able to listen for key presses even when you’re not focused on the element. So I ended up using useEffect and registering an event listener on the document itself which would call the set function that I got from useState. I also had to make sure to remove the eventlistener afterwards, otherwise there would be multiple listeners for a single key press. It worked fine but I wonder if there was a more elegant solution.

    • @VenelinBanov
      @VenelinBanov Pƙed rokem

      Your useEffect doesn't have any dependencies(which are the cause of most issues) and you're using it to register an event handler so it's a completely legit solution if you don't want to add an input with onKeyPress

    • @WebDevCody
      @WebDevCody  Pƙed rokem

      It sounds correct. It sounds like you need to manually add an event listener which useEffect is needed there; that’s syncing with an external system (dom events)

  • @amershboul9107
    @amershboul9107 Pƙed rokem

    very useful refactoring

  • @gll447
    @gll447 Pƙed rokem +3

    if you can handle the state of the password synchronously this way then what's the point of using useState at all in this example? since you are not dealing with data fetching or external sources. couldn't you just use a let for the pressedNumbers as well?

    • @abgezuckert.
      @abgezuckert. Pƙed rokem

      You need at least one state to rerender the component for displaying the success / fail message.

    • @WebDevCody
      @WebDevCody  Pƙed rokem +1

      You need state to force react to update the view

  • @chemedev
    @chemedev Pƙed rokem

    It's cleaner, I'd ask JSDoc or just a comment above the `if` logic and the handleNumberClicked just to remember to myself and coworkers what those blocks are doing.

  • @slahomar1497
    @slahomar1497 Pƙed rokem

    What the mic you’re using Sir ?

  • @LuKaSSthEBosS
    @LuKaSSthEBosS Pƙed rokem

    How do you do this renaming thing at 6:00?

  • @waytospergtherebro
    @waytospergtherebro Pƙed rokem

    A function called "useEffect" which performs 30 different tasks depending on the number of empty arrays you pass in to it is much, much, much easier to understand than component lifecycle methods that do the one thing they say they do and if you don't believe that then you are not a real Millennial engineer.

  • @devarsh5317
    @devarsh5317 Pƙed rokem

    can you show your vscode font?

  • @yousafwazir3167
    @yousafwazir3167 Pƙed rokem +1

    Do a vid where you build out an app using js doc instead of typescript. See if it is better.

    • @WebDevCody
      @WebDevCody  Pƙed rokem +1

      I doubt it would be better

    • @yousafwazir3167
      @yousafwazir3167 Pƙed rokem +2

      Yh I had the wrong idea, it works better for library authors like what sveltekit is doing.

  • @anazi
    @anazi Pƙed rokem

    useEffect & useState live in almost every file I have. Sorry I cannot change it, I like it its easier for me. I just hope they just don't deprecate it.

  • @owenwexler7214
    @owenwexler7214 Pƙed rokem

    “useEffect, aka useFootGun” - Fireship

  • @prasenjitsutradhar3368
    @prasenjitsutradhar3368 Pƙed rokem

    What is the name of this person? pls tell me anybody!

  • @three-card-dead
    @three-card-dead Pƙed rokem

    1st Approach is definitely the worst approach for all the reasons you listed and implied in my points below.
    2nd Approach is the most clear to the general programmer outside of the web dev bubble
    3rd Approach is better if you have experience with Java/TypeScript and some of the concepts in the React framework.

  • @mr.komp1004
    @mr.komp1004 Pƙed rokem

    I think useEffect its more readable way to that

  • @parlor3115
    @parlor3115 Pƙed rokem

    Not a front guy but the "useEffect" approach looks clearner and is more logical since it separates the logic for adding a new number from that that checks for password validity.

  • @pakast1n
    @pakast1n Pƙed rokem

    Next episode: why you probably do not need React 😄

  • @lkda01
    @lkda01 Pƙed rokem

    useEffect abstract all the steps you refactored, the bad is how useEffect implemented

    • @lkda01
      @lkda01 Pƙed rokem

      I thought useEffect means "when these changed, do this" but maybe I'm wrong.

  • @talyanikakoy4312
    @talyanikakoy4312 Pƙed 7 měsĂ­ci

    such a silly spaghetti code

  • @diyanslavov7401
    @diyanslavov7401 Pƙed 11 měsĂ­ci

    lol why is this so overengineered
    just have an event handler, put the currently clicked number in the array and do the logic based on its length and correctness
    always do the simplest thing that works

  • @NH-cb2jg
    @NH-cb2jg Pƙed rokem +7

    I think you should sit down 10 minutes before starting to record and think about video and problem you're working on.
    Clearly it's not helpful to see you fumbling around trying to come up with a good solution.

    • @ProwlerDigital
      @ProwlerDigital Pƙed rokem +4

      Let’s see you make some videos

    • @anricoj1
      @anricoj1 Pƙed rokem +5

      I like being able to see someone work through a problem. I feel as though that's the entire point of Cody's videos, unscripted raw thoughts. Even if he did "Sit down for 10 minutes before recording" I guarantee he'd walk out with a different solution anyways. This is how programming goes 90% of the time.
      This comment screams imposter syndrome.

    • @MrNaesme
      @MrNaesme Pƙed rokem +1

      Actually this is far more helpful. Instead of watching someone rapid fire through code while trying to figure out what's going through their head and how they came to certain conclusions, I now have an understanding of the thought process that goes into coming up with these solutions.

    • @WebDevCody
      @WebDevCody  Pƙed rokem +9

      That’s not the style I go for in my videos. I show you real software engineering, which is indeed fumbling around until you figure it out

  • @Famouzi
    @Famouzi Pƙed rokem +2

    What about reading state directly. You wont need to have variable passcode state.
    const finishedAttempt = pressedNumber.length === expectedPassword.length
    const isPasswordCorrect = pressNumbers === password
    ....{finishedAttempt ?
    {isPasswordCorrect ? Success! : "Bad password"}
    : null}...

  • @herzog0
    @herzog0 Pƙed rokem

    In this approach, my variable is always changing between re-renders. And even though it gets corrected again by the if statements, I prefer to make them as stable as possible to avoid my messy hands from introducing a mistake in the future. Therefore, I would still encapsulate everything, but in a reducer:
    type InputState = "typing" | "success" | "error"
    type ReducerState = { inputState: InputState; password: string }
    ...
    const [state, dispatch] = useReducer(
    (prevState: ReducerState, action: number): ReducerState => {
    const updatedPassword = prevState.password + action
    if (updatedPassword.length !== PASSWORD.length) {
    return { inputState: "typing", password: updatedPassword }
    }
    if (updatedPassword === PASSWORD) {
    return {
    inputState: "success",
    password: "",
    }
    }
    return {
    inputState: "error",
    password: "",
    }
    },
    {
    password: "",
    inputState: "typing",
    }
    )
    ...
    onClick={() => dispatch(n)}
    ...

  • @shoaibreactnative4739
    @shoaibreactnative4739 Pƙed rokem

    what you think of the following code. to reuse the state and what you think of it's computation and performance.
    const [state, setState] = useState({
    email_length: 'medium',
    content_count: details?.selectedRows,
    email_style: 'Casual',
    sale_type: 'Product',
    sale_message: '',
    });
    const updateState = (category, option) => {
    setState((prevState) => {
    return {
    ...prevState,
    [category]: option,
    };
    });
    };
    onClick={() => updateState('email_style', 'Casual')}

    • @WebDevCody
      @WebDevCody  Pƙed rokem

      I've done that before, seems fine imo