Goodbye, useEffect: David Khourshid

Video Statistics and Information

Video
Captions Word Cloud
Reddit Comments

Much of this presentation makes me uncomfortable.

Yes hooks are overused. Lifecycle methods were overused before too. It's often a cleaner and more flexible design to save React components for rendering and do everything else somewhere else. That's ultimately where this presentation goes by the end and to that extent I agree with it.

But React is now the dominant UI library for client-side rendering of web apps. We are way past the point where Hyrum's Law becomes relevant. And whether or not it is a good idea the reality is that many teams have shoved the kitchen sink into their React components and the presentation of hooks has actively encouraged that style. Developers do rely on the behaviour of useEffect or on hooks from libraries like react-query and swr that are used in a similar way. If you're going to pretend that React is being maintained and made available for general use by the community and not just as something for internal use at Facebook then aspects like compatibility and having good documentation are really important.

I think what is really annoying me here is the argument made several times in this presentation that the "official" line is X or the "intended" use of something is Y. Says who? The official React documentation for useEffect presents almost exactly the opposite perspective and has for several years. The source for the irritating claims seems to be some mostly unacknowledged goalpost moving in the new documentation that is years late and still not finished. And the big argument about multiple renders causing repeated effects relies on some potentially surprising behaviour changes in a version of React that was only released a couple of months ago when hooks have been in widespread use for well over three years now.

In short the attitude here seems to be a combination of casually dismissing the impact these changes might have on huge numbers of applications that have followed widely used patterns for several years and gaslighting as if the failure of those patterns to work as expected any more is their developers' fault and not because of a very recent change in direction from the React developers that actively changes behaviour in surprising ways.

👍︎︎ 39 👤︎︎ u/Silhouette 📅︎︎ Jun 07 2022 🗫︎ replies

More confusion, more quirks, still no documentation, this bs pisses me off.

👍︎︎ 25 👤︎︎ u/BaniGrisson 📅︎︎ Jun 06 2022 🗫︎ replies

TLDW? In general it's good to summarise longer videos.

👍︎︎ 101 👤︎︎ u/TScottFitzgerald 📅︎︎ Jun 06 2022 🗫︎ replies

Okay what I understand is that React 18 is making me change where I fire async network calls, because I do not want those firing twice. Oh, and its not immediately clear how this common use case is handled. great.

👍︎︎ 46 👤︎︎ u/11010001101001 📅︎︎ Jun 06 2022 🗫︎ replies

Person in the video here, thanks for sharing!

There's a lot to talk about with regard to useEffect(), and I wasn't able to capture it all in this talk. In future talks, I will be discussing new patterns, updated React core team guidance, and more fundamentals on effects in React.

Feel free to ask me any questions about this talk, happy to answer them.

👍︎︎ 57 👤︎︎ u/davidkpiano 📅︎︎ Jun 06 2022 🗫︎ replies

React the library which creates problems for other libraries to solve.

👍︎︎ 29 👤︎︎ u/Zanena001 📅︎︎ Jun 06 2022 🗫︎ replies

React honestly makes angular look very appealing these days

👍︎︎ 7 👤︎︎ u/gh0stF4CE7 📅︎︎ Jun 07 2022 🗫︎ replies

What can I say, front end development is really tiresome and tiring.

👍︎︎ 8 👤︎︎ u/[deleted] 📅︎︎ Jun 07 2022 🗫︎ replies

I'm baffled that people would ever do this pattern on the left.

What would lead someone to think they ever needed useEffect for this pattern? This is something that has existed since the class component days. useEffect is not some fancy place to just put any effect (as said in the talk). It's just a way to hook into an effect which is based off of prop values changing. Creating internal state which you change the value of so that your useEffect fires again is crazy and shouldn't happen in any version of react, regardless of react 18, 17, or w/e version you are on.

To clarify:

Let's look at the example in terms of old class components. This would be the equivalent of setting your "fetching" state to true, then in componentDidUpdate, checking if fetching state changed, and if it did, submit for your form. No one would ever do that!

👍︎︎ 17 👤︎︎ u/mikejoro 📅︎︎ Jun 06 2022 🗫︎ replies
Captions
foreign [Music] [Music] hello everyone how's everyone doing good yeah how many of you feel like this right now happy right okay awesome how many of you uh that's the wrong one all right how many of you feel sad okay how many of you feel you know okay like a little bit curious about what i'm going to talk about all right yeah you're like why you know why are we talking about use effect and why should we get rid of it so we are going to be talking about everyone's favorite hook today which of course is use effect and so i know it might not be everyone's favorite hook but um we're going to talk about it because it personally for me has caused a lot of problems and especially like even from when i was starting with react and react hooks and even till now like there's just a bunch of things that can go wrong so first of all if you're struggling with use effects don't worry because even senior reactives you know struggle with it people who have been doing reacts from the very beginning you know and even those people we all have the same experience like with react hooks because um if honestly if you've done class components it's like all that knowledge sort of goes away once you once you've started using hooks but that large dependency array you know the ones i'm talking about the complicated if statements i mean those are typical you know it's just a really awkward hook so that's what we're going to talk about today and if i wanted to summarize my slides like if you have somewhere to go and you want me to just summarize it real quick for you i'll just say use effect is not for effects now so this might actually leave you a little bit confused so um where like how did we get here so when we were doing effects and you know class components how many of you remember that where are my elderly react devs okay so we had three places to put them we had componented mounts right we had componented update which is whenever we had state come in and or some props change or something we're like okay that's a really good opportunity for me to fire an effect um or component will unmount and so this is a good place to do on subscriptions or to do some sort of cleanup but these were the three main places that we had in class components to do effects so now what do we have do we have those same three places well with the use effect hook you know if we pass an empty dependency array you know we have componented mounts sort of we're going to talk about some foot guns there in a bit we have um componented update where we could say like if these things change then i want this use effect to run and we also have component will amounts sort of like you have this empty dependency array it's really awkward you have a function inside of a function you know we're not haskell what are we doing here so i just want to say that use effect is not a life cycle hook and so a lot of us think about like okay effects we're used to you know just putting them in life cycle hooks but use effect is not really for that purpose and react 18 actually makes that really really clear also the default behavior of use effect is an infinite loop and so you might be thinking like okay i've been using effect enough to know that i need a dependency array right and so everyone should know that so why does everyone run into this like infinite loop scenario so uh here's an example like i just have an example where we set count count plus one you might think okay this is a side effect this is only going to run once but in reality we we have this happen okay so use effect is also not a state setter you could set state in it but if you need to set state you could do that in other places too okay um this has been like one of the biggest problems especially in the very beginning when i was making api calls and when you put fetch requests in there and they start looping infinitely things go really really wrong so um this is another example and this is actually straight from the react docs as it exists today not the beta docs but the actual react docs where do you see something wrong here there's no dependency array so this this seems like um i flew here all the way from orlando it really feels like um when i went on the plane and i saw no one with masks you know it was a little bit dangerous a little bit uncomfortable and uh sometimes ugly so it just feels weird but thankfully the react documentation does introduce this idea of a dependency ray but it's at the very bottom so you know you have to scroll all the way down and it's a tip it's like hey here's a cute little tip you could you know use a dependency array but now all of us know like we need that so um here's what we really expect when we use effects now that we're used to all these foot guns we we think we're gonna do this effect whenever something here changes in the dependency array and we're like okay that's pretty simple i i could do that i could you know manage my effects that way but the reality is a little bit different and my slides aren't exactly working but that's okay um so the reality is more that we um you know we have a big if statement in there and we have a big dependency array and it's just a little bit weird and so one of the reasons for this and one of the reasons why we tend to use use effect is because the imperative approach to doing effects is when something happens execute this effect it's like a do this like that's the definition of imperative so what's the declarative approach of use effect well when something happens it will cause a state to change or props to change or something in the component to change and depending on which parts of that state changed which is a dependency array this effect should be executed and that should only happen if some condition is true you see how confusing that is oh also react may execute it again because of concurrent rendering does uh so like okay we we have imperative we have declarative but really it's more like this is implicit or this is explicit and this is implicit and i prefer explicit over implicit so um yeah uh you know when we use effect we have this like just massive you know crazy boolean jumble and you know how much i love my boolean variables like i see them all the time in use effect and here's a few examples by the way um i'm not going to name any of the companies uh but i i found this just an open source repos and really it's not their faults because used effects just an awkward hook you know we have these conditionals really long dependency arrays here's another example here's one of my favorite examples which isn't actually there i if you want you know come find me i will show it to you later it's by again one of the companies i will not mention but um it's a really fun one so where do effects go you know i i'm talking a lot of you know crap about use effect um so where should these effects go you know when we're looking at the components we see there's a few possible places right we know that we can't do any side effects in render we already know that you know we could use use effect and we're going to talk about when you could use it but it is a little bit awkward so where's left maybe outside the component what does this look like this is weird like you know we're supposed to have everything inside our components right so yeah if you decide you know what this actually is a good use case for use effects like um i'm listening to what david says but i'm going to put it in there anyway because that's just what i'm used to doing here's the problem react 18 will execute your effects twice on mount in strix mode how many of you have used react 18 have been bitten by this already so a few of you the others you know you you will you'll experience it it'll be bad and so what happens what react 18 is doing is we're mounting the component which will cause the effects then we're unmounting it which uh it is simulated in strict mode and so that will be a cleanup of the effect and then we remount it and so it's going to be executed again and so the reason it does this is because um it's trying to tell you that you're not using use effect for its intended purpose um which is what i'm going to talk about so it's really sussing out all of those effects that really shouldn't be there so use effect really feels like use defect at this point um and also like a foot gun so you're like why am i using this hook you know it's a and what is use effect really used for anyway so the answer is use effect is supposed to be used for synchronization and i suggested that use effects should really be called use synchronize because you're supposed to use use effect that is really confusing to say by the way you're supposed to use effect when you have something that you need to synchronize with so examples would be a subscription like this and also dan says this as well i feel like my sites have no credibility unless i have a dan tweet on there so he says this as well that if you don't use use effect um you know or if you're trying to manage your data with use effect you're gonna have a lot of problems it's really used to synchronize it with some external system but another classic example is uh just tracking things in the dom so adding event listeners like a pointer move doing your cleanup and trying to keep this dependency array as small as possible so we have two types of actions or effects really we have the synchronized effects which we just talked about those are the subscriptions the event handlers all of that and we have action effects or what i call action effects these are your fire and forget effects and again um with react 18 you are going to have that unmounted remounts happening through the strict mode and if you turn off strict mode react 18 is going to do it anyway because of some concurrent uh rendering so this is just something you have to be careful of but typically effects that are based on synchronization are safe to stop and remounts just because they're not those one-off action effects so then where do action effects go and the answer the official answer is actually event handlers so whenever possible you want these effects to go inside of things like on submit on click things like that um so i both like and don't like this answer even though it's the official answer um because we're doing imperative logic it feels like it's inside of render but it's not it's actually happening outside of render and also you have implicit code in your code base so um when we look at the beta documentation which hopefully you've all read they're excellent one of the things it says is that event handlers are the best place for side effects and so further down the documentation when answering the questions where you can cause side effects it says that these side effects usually belong inside the vent handlers and so when uh you know when concerning use effects like when do we actually use use effect uh we say that or the documentation says that this should actually really be your last resort so you heard it from the documentation maybe you heard it from me first maybe you should read the documentation before coming to my talk and i wouldn't have to talk about this but i actually really enjoy talking about this so um yeah the problem is when we put effects inside of our components like rendering life cycle then we run into the problem like we talked about in uh react 18 where these effects can execute multiple times because they're at the mercy of the component rendering but if you put them in the event handler now you don't really have that problem like it doesn't matter how many times that component is going to render these effects are actually going to only happen once because it's guaranteed and reacts that when you go from state to state talking about this like a state machine then these effects this transition will only happen once but rendering might happen multiple times so effects can or effects happen outside of rendering uh but obviously i have a little bit of a problem with this if you start putting your effects inside of event handlers then you get into some messy uh situations where it might look like this um again my slides aren't showing all the slides but uh this eventually expands where you have is loading you're doing set loading set error you know you might do a fetch inside of there and you might do a lot of state management and all of a sudden these event handlers become multiple lines long where you really want to keep it just to one line so um in react a popular mantra is that ui is a function of states and so that whatever state you have it's going to render a ui and so we could actually derive um this whole idea which redux popularized where given the states in an event that happens now you have a next date so the problem with this though is that you really have no place for effects it doesn't really fit into this function so where do effects happen well um you know we have many different answers from many different state management libraries like middleware callbacks monads i think um but the real answer is straight state transitions and it always happens in state transitions and so the reason for this is that the only way that you could trigger an effect is to do something so something needs to actually cause that effect to happen effects can't just happen out of the blue and so typically if you catch it within the event handler then you know that's that's the a great place for an effect so instead of just this whole idea of a state and when you get an event you get a next date we have states plus events equals next date and effects so this is called managed or declarative effects where um by the way if you have your bingo cards out i am talking about state machines so you could mark off that box um but state machines like this this model over here of um you know state and events equals next and effects this is all you need to understand when um talking about a state machine like these this is how state machines work so in a state machine you have an initial state and you might have a finite number of states and in the transition that's where you define the effects so you could say when this event happens like load then this fetch data effect also happens and so um you know that equation just becomes a really convenient way to define hey this effect is supposed to be executed when we transition from this state to the other state and these effects aren't executed by the way they're basically handed off to something that's going to interpret that and say okay i'm going to save the state and i'm going to take these effects and i'm going to execute them so your state machine these uh transition functions still remain pure and um so there's uh some pretty cool features with state machines as well you can see that the fetch data is happening in both the load and the reload state and um so state machines have this idea of entry exit and transition actions as well so it's pretty convenient um so where how can we do this like how can we eliminate use effect and actually execute effects while we're you know um dispatch or like just handling events so i have this uh hook here called spicy dispatch and no i'm not going to make it in npm library or something like that i'm just putting it on the screen to be spicy but our dispatch here is a little bit fancy because inside the dispatch itself we're getting the next dates and we're determining which effects should be run given the state the event and the next state so basically that's the transition because those are the three parts of it and um we're executing those effects now this is uh you know this is left as an exercise to the reader uh but you could just you know say okay when the state is loading and i just came from the idle states then i'm going to execute this effect um but the main point here is that all this is happening within the dispatch itself and so um when you think about when you dispatch stuff that's happening right in the event handler all right so where do action effects go event handlers right technically sort of not really so they really happen in these state transitions but these state transitions especially in react just so happen to be executed at the same time as these event handlers so as a step one i would say try to move all of your effects away from use effect and put them in those event handlers unless of course their um you know their uh synchronizing effects or activity effects so um a better way to manage this at least in my opinion is to use external stores and so i don't really recommend i i love this hook by the way using external store but i don't recommend you use it directly so um using external store is really cool because you have a component and this component can communicate with a store in which it could sync with it and it could also interact with it because the store might have methods such as dispatch or send or whatever and this door can be the thing that both holds your state and executes all of your effects so it's pretty nice here's an example of its usage the api is actually pretty straightforward you grab some store from somewhere i know that react redux uses a using external store i believe and also x8 as well and you provide a way to subscribe and to get a snapshot of that of that state and then you could of course interact with it in any which way you want so uh x8 of course is my library uh it's a library for state machines and state charts and it also lets you declaratively manage your effects too and so x8 is using sync external store under the hood as well this allows xda to be in total control of executing these effects so these effects will execute without you having to do anything inside of use effect and other state management and react libraries work actually the same way where basically you're delegating control of the effects over to those libraries instead of you having to do it yourself so in x date just like we talked about with entry exit and transition actions you could find those right in your i'm just going to call it a fancy reducer it's a machine definition you could define your entry and exit actions your transition actions and even invocations which are sort of like those synchronizing activity effects that we talked about these are the ones where if you weren't using a state management library you would typically put in use effect so uh when it comes to state management you know we think about state stores we think about state updates and subscribing to data and getting new data as as it comes in and events dispatching but in my opinion this is only part of the picture you know we also want the ability to communicate with multiple stores communicate with those stores like send events to it receive events from it effect management which is you know the most important part of this talk and also you know maybe even handle finite states and transitions and this to me seems like state management plus plus now we're talking about state orchestration so um i'm going to go over a couple more patterns here sometimes it's actually really hard if not impossible to find that event handler and to execute an effect only once in there so what you have to do is you have to do this weird uh what's called a ref flag and so you would say is this executed yet you would have a ref in there said it's a false first and then you would start um your use effect and if it's already executed you're not going to um you know execute it again so you do your thing and then you set executed ref.current is true and so um that way when your effect reruns because of react 18 doing its thing or some other reason it's going to check that flag which is going to be stable so that flag will stay true even when your component virtually unmounts and remounts and so this will allow you to only run your effects truly once so um you know just think about this as like an escape uh an escape hatch for if you really want to use effect and so you might be looking at this flag and thinking okay this seems like a really big red flag like why am i using a wrath in my effects but honestly this is the least awkward way to do it so yeah and also what about fetching data you know we have fetch on render this is one of the most popular uh you know use cases of use effect we have used query use swr but i'm here to say that fetch on render is actually a lie you know sorry to those uh libraries react query swr because you're supposed to or at least the react team wants you to really move towards a pattern of render as you fetch and so suspense is really really great for this and so this means that you're going to find that event handler that we talked about you're going to start fetching in there and all you have to do is read that in your components and make use of suspense or you could ditch the usefx altogether and use frameworks such as remix or next which make it really easy to just get rid of these um they they didn't pay me but they will hopefully i'll talk to them all right so uh just to give you an example of like the code that you save with fetching data this is a typical thing that we do and honestly this is what i taught at react training workshops where it's like okay you have to set this awkward cancelled flag and then you fetch some resource and then you um if that if it was canceled due to the cleanup then you have to make sure not to run the effect again uh but look at suspense this is all you need and so you know i know you love your use query and use swr but really moving towards suspense just makes things a lot lot easier all right so speaking of code save this is our use effect example this is when we move it into an event handler and so uh when we take this and we say you know what i'm going to let these effects run in some store that both manages my state and manages my effects then this shrinks down to this and all you're doing in that event handler is sending an event it's all you're doing and so it doesn't matter which library you use to do this um obviously x8 handles effects react has a new action listener middleware that does it and i'm sure other state management libraries do it it's just like actually my my call to action for these other seat management libraries is to realize that effects are state management they shouldn't be treated as this other thing so don't put side effects aside and really really manage your effects with your state management you could do it in a declarative way you could do it in a pure way but just that notion of saying here's the effects that i want to run due to this date transition that's really powerful and that's actually going to help you with testing as well so in summary sorry use effects is for synchronization not for effects even though synchronization can be considered an effect that's not the main purpose of use effect state transitions are what trigger effects and effects go in event handlers so find the event handler that triggers your effect and put the effect in there also render as you fetch with suspense and model effects with state machines so with that thank you react-a-thon [Applause] you
Info
Channel: Real World React
Views: 224,749
Rating: undefined out of 5
Keywords:
Id: HPoC-k7Rxwo
Channel Id: undefined
Length: 26min 0sec (1560 seconds)
Published: Fri May 27 2022
Related Videos
Note
Please note that this website is currently a work in progress! Lots of interesting data and statistics to come.