Тёмный

Asynchronous tasks inside React.useEffect can create Stale Closure BUGS! 

Joel Codes
Подписаться 4,1 тыс.
Просмотров 2,4 тыс.
50% 1

Stale closures can catch you off guard when using React.useEffect. In this video I will demonstrate what the bugs are, explain why they happen and also provide solutions to how to solve them.
Be Cautious of React.useEffect Race Condition Bugs:
- • Be Cautious of React.u...
Subscribe to my mailing list: joel.net
Twitter: / joelnet
Dev.to: dev.to/joelnet
Medium: / joelthoms
0:20 Thanks to New Subscribers
0:40 What is a State Closure Bug?
1:05 What does this code do?
1:45 Why does this Stale Closure Bug happen?
2:10 Recommended way to set the State
2:40 Conditionally updating values
3:39 Add variables as a dependency to React.useEffect
4:09 The SOLUTION is to use useRef
6:03 Recap of the solution
6:56 Some quick TIPS
7:37 SUBSCRIBE!
7:49 Dumpling!!!

Опубликовано:

 

27 сен 2020

Поделиться:

Ссылка:

Скачать:

Готовим ссылку...

Добавить в:

Мой плейлист
Посмотреть позже
Комментарии : 20   
@sabin-pandey
@sabin-pandey 3 года назад
yes please make a video about closure as well.
@JoelCodes
@JoelCodes 3 года назад
It's in the queue!
@aliraza7538
@aliraza7538 2 года назад
Awesome 😍
@JoelCodes
@JoelCodes 2 года назад
Thanks 🤗
@hardwired89
@hardwired89 Год назад
Need more about react closure :(
@diegommf
@diegommf 3 года назад
Excelent! Just what I needed, thanks, man!
@JoelCodes
@JoelCodes 3 года назад
Glad it helped! There's a couple of gotchas with useEffect, but once you know, they're not too bad!
@9429963654
@9429963654 3 года назад
Crisp and Clear explanation Joel! I have one question: The reason we have lastest value in countRef but not in count is because countRef is an object and count is a variable, right ? I mean, when the closure is created, the closure has the value for count at the time of the creation ( being 0 - You can also say closure has a COPY of the variable ), and a reference to the object countRef ( so no copies are made ), and because we have the reference to the object, we can access the correct value.
@JoelCodes
@JoelCodes 3 года назад
The copy is a good way of thinking about it, so if that value in the closure is updated, it is updated only inside that closure. It's similar to passing a value to a function. function abc(x) { x = 123 }. In this example x (the copy) inside of the function is changed, but outside the function, nothing has been changed. The ref is able to change because it's an object. Also similar to a function. function abc(x) { x.current = 123 }. In this example, x is mutated and so the value outside the function is also modified.
@7urkoGaming
@7urkoGaming 3 года назад
I understand the solution but It's weird to have to increase the ref and state at the same time. I mean two operations to have the same result
@JoelCodes
@JoelCodes 3 года назад
It's less than ideal and there may be better solutions. The ref contains the real value but updates won't trigger a rerender. Updating the state will trigger a rerender, but may contain stale values. ¯\_(ツ)_/¯
@qwan1
@qwan1 3 года назад
​ @Joel Codes I think having the count in the dependency array is fine. Yes you're calling cleanup after every update, but that is exactly what you instructed React to do because React needs to create a new interval for each update, per your instruction. In your example setInterval is a bit contrived and is an API that doesnt change so it makes sense you're thinking of how to "preserve" it. But thats not the usual workflow. What if in your app you want the interval delay be adjustable? I would recommend reading overreacted.io/making-setinterval-declarative-with-react-hooks/ and theres something there that can help you get the best of both worlds.
@JoelCodes
@JoelCodes 3 года назад
In other situations, this would be fine. But for this specific case, the code is using a timer (setInterval). When cancelling / re-initializing the timer on each state change, the timer could count too quickly or too slowly. In other words, the interval could tick off beat. The useInterval from that article is a better approach and basically the next step from this video (for setInterval), which is to extract the `setInterval` code into it's own hook. I didn't demo a solution like the `useInterval` because the problem I was demonstrating isn't limited to `useInterval`. It's a problem with all asychronous code inside of `useEffect`. For example, if there was a `fetch` request, or another Promise or a callback, the same stale state problems would exist. `setInterval` was just a quick way of adding async code for a demo. Cheers 🍻
@qwan1
@qwan1 3 года назад
@@JoelCodes I see why you're worried about it ticking too fast or too slow. You don't want to go super in-depth like useInterval but you're also worried about very granular things like interval ticking "off-beat". I think the interval would be very very close - as close as it could be. It will never be exactly 1s, as you would have to take into account of React's rendering and reconciliation (which takes cycle, more if render is batched), and browsers' own event loop. So accounting just for React's update life-cycle, and setting a new timer each second, while it feels icky, shouldnt be something we'd worry about in the average use-case, esp in tutorials. Just my 2c though!
@KepiFromCzech
@KepiFromCzech 3 года назад
What about solution without useRef: `setCount((state) => state >= 10 ? state : state + 1)` ?
@JoelCodes
@JoelCodes 3 года назад
For this example this would be a good solution, control the updating from within the setCount! But this solution won't work if your condition needed to reference values from other states.
@RusuTraianCristian
@RusuTraianCristian 3 года назад
Hey Joel, love your videos. Just dropped in to say that! :D Oh, btw, what's that vscode syntax theme? It's adorable.
@JoelCodes
@JoelCodes 3 года назад
Oh hey thanks! I really appreciate that! The theme is called moonlight and the font is FiraCode. It's one of my favorite setups! Hope to see you around. Cheers! 🍻
@JohnSmith-kw6be
@JohnSmith-kw6be 2 года назад
And this is the reason why I hate ReactJS. It makes programmer write code that is not intuitive. Everything is asynchronous by default without any proper tools to synchronize them. Here is an alternative solution of the problem presented in this video without using useRef(): setCount((state) => state >= 10 ? state : state +1);
@JoelCodes
@JoelCodes 2 года назад
Ya I get that. I definitely understand. The tooling is improving. Which I guess means you aren't the only one who feels that way.
Далее
React Hooks Closure Problems
7:21
Просмотров 24 тыс.
Kettim gul opkegani😋
00:37
Просмотров 1,1 млн
FUNCTION OVERLOADING IN JAVASCRIPT
3:52
Просмотров 4,8 тыс.
Custom Array Sort Algorithms in JavaScript
5:56
Просмотров 2,7 тыс.
JavaScript Closures in FIVE Minutes
5:00
Просмотров 26 тыс.