Unintuitive behaviors of React Hooks

  Рет қаралды 23,871

Theo - t3․gg

Theo - t3․gg

Күн бұрын

Пікірлер: 105
@omomer3506
@omomer3506 5 күн бұрын
Using cleanup function to store prev state feels diabolical
@kika7497
@kika7497 6 күн бұрын
its nice to see that we have gone from something simple like: prev = count++ to something like this, all because of the hidden react hooks/effects and render sequence.😜
@AngelzWrath11
@AngelzWrath11 6 күн бұрын
react-use doing it the wrong way at the end made me lose a lot of confidence in that library
@michaelns9887
@michaelns9887 5 күн бұрын
it is "the wrong way" because Theo said so?
@AngelzWrath11
@AngelzWrath11 5 күн бұрын
@@michaelns9887 No, it's just objectively wrong. The value returned from that previous hook is actually the current value, but the value is updated after the render. If any other state changes causing another render, you'd see it displaying the current value rather than the previous value.
@jakehobbs1
@jakehobbs1 5 күн бұрын
i've had other issues w/ that library too. i reach for usehooks-ts first now.
@Unc3
@Unc3 5 күн бұрын
It works fine if you need to show the value. It doesn't if you need to use the value.
@krs_77
@krs_77 2 күн бұрын
I don't think we can say that it's objectively wrong, as it won't return the current value, but, on a given render, it will return the value "captured" during the last render. The consideration about any other state changing and causing the display of the current value, it's not a sign of it being broken, it's just due to the fact it's not meant to return the "last different" value, but the value from the last render, which can be equal to current one, if the last render hasn't changed it, but has set it to the same value. In fact, I've seen that they also have another hook, named usePreviousDistinct which takes that into account.
@h4ggs
@h4ggs 6 күн бұрын
It seems like count and previous count should be combined into one piece of useState. Isn't that a principle that I feel like I've heard Theo say before? Something like "if two pieces of state are always updated together, they should just be one piece of state".
@nwsome
@nwsome 6 күн бұрын
Generally, yes. Doesn't really matter here though, since neither setter is exposed outside the hook and they are always batched anyway.
@SSpirite
@SSpirite 6 күн бұрын
yes. You can use useReducer for it.
@Emmanuel-lz4dc
@Emmanuel-lz4dc 6 күн бұрын
This is the correct answer
@purpleboi-y8p
@purpleboi-y8p 6 күн бұрын
Remember, he used useEffect here while in his previous videos he was/is pushing for devs to not use the useEffect hook!
@benheidemann3836
@benheidemann3836 5 күн бұрын
When you set state in a cleanup function, it will re-render twice in production, not just dev mode. This is because the order of events here is render (due to initial state change) -> cleanup (due to re-render) -> effect (due to render) -> render (due to state set in cleanup). This is not a good implementation of previous value because 1) as demonstrated, it’s hard to understand, even by experienced react devs like Theo, and 2) it causes multiple renders (not an issue in isolation but from experience this stuff piles up and can exacerbate other issues in the app). A much better approach would be to batch the state updates as others have suggested. Probably this is best done behind a well implemented abstraction to usePreviousState.
@DeyLakIT
@DeyLakIT 6 күн бұрын
That usePrevious hook is not meant to be used in render and there is nothing wrong about it. It's meant to be used to compare current prop value with the value from the previous rendering. It can be useful in more complex scenarios, where you should perform some side effect, when you detect a specific change in a prop. That's why is stopped working, when you added a second setState before the first one. There were actually 2 renders (may be batched), but only one useEffect run. So it's important that the useEffect you use should not have any dependencies, exactly like react-use did it. If you need to actually render the previous prop value, if think the provided example is fine. But I've never really needed it in my practice. I find the mental model for usePrevious as a value from previous render much more usefull.
@felipegustavo5531
@felipegustavo5531 6 күн бұрын
which use case you find to the usePrevious hook normally?
@DeyLakIT
@DeyLakIT 5 күн бұрын
@felipegustavo5531 to detect some transition states and perform effects. Like closing modal, when isOpen prop is changing from true to false. Or isLoading state changes. Also can be usefull in business logic, like "when user is changing this input to a specific value, you should do something". Usually, you combine this usePrevious hook with an actual state which is set in a side effect, caused by the detected transition state.
@DeyLakIT
@DeyLakIT 5 күн бұрын
@@felipegustavo5531 to detect some transition states and perform effects. Like closing modal, when isOpen prop is changing from true to false. Or isLoading state changes. Also can be usefull in business logic, like "when user is changing this input to a specific value, you should do something". Usually, you combine this usePrevious hook with an actual state which is set in a side effect, caused by the detected transition state.
@DeyLakIT
@DeyLakIT 5 күн бұрын
@@felipegustavo5531 to detect some transition states and perform effects. Like closing modal, when isOpen prop is changing from true to false. Or isLoading state changes. Also can be usefull in business logic, like "when user is changing this input to a specific value, you should do something". Usually, you combine this usePrevious hook with an actual state which is set in a side effect, caused by the detected transition state.
@DeyLakIT
@DeyLakIT Күн бұрын
​@@felipegustavo5531 for example to detect some change in isOpen or isLoading state and perform a side-effect. The benefit of it is detecting the change in props immediately and not after a setState call, the means avoiding an additional rerender.
@dough-pizza
@dough-pizza 6 күн бұрын
I just faced this ref issue and was hella confused and you upload this gem! Thanks Theo!
@priyanshshah6905
@priyanshshah6905 6 күн бұрын
my brain desoyred it self, but that explanation helped so thanks!!
@11WicToR11
@11WicToR11 6 күн бұрын
loving these types of videos where you explain some quirk of react ...keep em coming :)
@cooldotty
@cooldotty 6 күн бұрын
I feel like using a quirk that makes a set state not rerender is less intuitive, but hey, if you’re hiding it in a hook I don’t care as long as it works
@adityacapalasetty7232
@adityacapalasetty7232 4 күн бұрын
Yes Theo please make a comprehensive video on the render cycle of react it would be a great help.
@ryannathanwilson
@ryannathanwilson 6 күн бұрын
setCount(p => { setPrev(p); return p + 1 });
@lucaswong98
@lucaswong98 6 күн бұрын
simple is the best
@titbarros
@titbarros 6 күн бұрын
Exactly my first thought
@diegoarf_
@diegoarf_ 6 күн бұрын
Could this be done with previous as a ref? Or is it necessary for it to be a state if we want to use it on render
@ajaysihota2299
@ajaysihota2299 6 күн бұрын
Needs to be state to be reacty
@ryannathanwilson
@ryannathanwilson 5 күн бұрын
@@diegoarf_ if you want to guarantee that the UI is always rendering the value (especially given that the component will evolve and other items will trigger rerenders) then state is best, though there may be cases where a ref would be fine.
@emmanuelxs6143
@emmanuelxs6143 6 күн бұрын
Learnt so much about react rerender circle thanks 😊 And yeah a full break down is really needed 😅
@jamesgulland
@jamesgulland 5 күн бұрын
Theo I would love to see a breakdown of the React rendering process, it’s something that still gives me headaches! Biggups
@lxn7404
@lxn7404 5 күн бұрын
I'd love a full breakdown of react rendering process 👍
@tzuilee588
@tzuilee588 5 күн бұрын
this is actually super helpful, clear explanation
@simboy
@simboy 5 күн бұрын
We need use state to have optional 1. Dependency argument like use effect 2. 2. A to function to run everytime time u call setState for any logic the need to happen 3. A way to rerender the progrmticly
@alejandroechavarria539
@alejandroechavarria539 5 күн бұрын
React docs invite to avoid useEffect unless it is necessary. useEffect is usually the cause of many bugs. The reason for that is that modern react is inspired by the functional programming paradigm which invite the avoidance of the effects. In this case, the most robust approach will be to put the setPrev in the click handler. This also will avoid two rerenders and it is a simper solution.
@sunny8k
@sunny8k 5 күн бұрын
There's been some convoluted frameworks, but React is still king for that. So much boilerplate and unintuitive and overly verbose setup to do anything. Reminds me of the JavaServer Faces days of needing to know the ins and outs of the entire lifecycle to do anything productive - which is a terrible sign. Really hoping another framework can dethrone React's strangehold on the professional frontend world.
@piaIy
@piaIy 5 күн бұрын
There's a simpler solution for local state that doesn't depend on props (requires explicit type definitions in TS though): useReducer((state, current) => [state[1], current], [initialPrevious, initialCurrent]) It returns a [[previous, current], setCurrent] tuple.
@0815HansGans
@0815HansGans 6 күн бұрын
function usePrevious(value: T) { const currentRef = useRef(value); const prevRef = useRef(value); if (currentRef.current !== value) { prevRef.current = currentRef.current; currentRef.current = value; } return prevRef.current; } How about this? Saves one render cycle.
@abuzain859
@abuzain859 6 күн бұрын
Your approach is amazing, but I like his approach because his code seems more readable to me. However, this is just my personal preference.
@bluecup25
@bluecup25 6 күн бұрын
big brain
@piaIy
@piaIy 5 күн бұрын
It's not allowed to write or read ref.current during rendering, except for initialization.
@bluecup25
@bluecup25 5 күн бұрын
@@piaIy says who
@piaIy
@piaIy 4 күн бұрын
@@bluecup25 the React docs
@SigmaTapion
@SigmaTapion 6 күн бұрын
I'm scared of switching over to react when I'm used to vue where I can just do a little watch and set the old value onto the prev value ref
@bishal_mishra99
@bishal_mishra99 5 күн бұрын
Vue is much more intuitive and I was thinking of same thing this morning 😂 - most companies should use vue seriously - front-end job market is bloated with react soydevs
@justindouglas3659
@justindouglas3659 5 күн бұрын
No need to switch over if it's not required
@philo23
@philo23 6 күн бұрын
I always end up having to lookup this pattern up when I need it, and the useRef way always felt wrong. I’d never even thought about using useEffect’s cleanup to do it instead, that definitely reads like a much more intuitive way to do it. Something tells me I’m gonna remember it for next time now!
@tabletuser123
@tabletuser123 4 күн бұрын
thats why i stopped using react bruh too many sweats
@t4styycs
@t4styycs 6 күн бұрын
I mean in this case u could just derive the prev count state on each render no need for two useStates but for other useCases it is correct
@kristemmerman921
@kristemmerman921 5 күн бұрын
Love the Epic React ad!
@vvvvvvvvvwv
@vvvvvvvvvwv 5 күн бұрын
I would probably just create a useStateWithPrevious hook that just updates the prev value in the setter function. Relying on the framework to call things in a certain order seems unnecessary and harder to reason about. function useStateWithPrevious(value) { const [current, setCurrent] = React.useState(value); const [prev, setPrev] = React.useState(); const setter = (newValue) => { setPrev(current); setCurrent(newValue); }; return [current, prev, setter]; }
@tririfandani1876
@tririfandani1876 6 күн бұрын
no need for useEffect & useRef const [[prevCount, count], setCount] = useState([0, 0]) setCount(([_prevCount, _count]) => [_count, count + 1])
@krisbude9607
@krisbude9607 6 күн бұрын
it is about showing the previous version of any state. ... in this example it is just a counter. But the state could be a word, and you also want to display the previous word for example. Then your solution does not work.
@diego-aquino
@diego-aquino 6 күн бұрын
I believe it does work. You are essentially storing the previous and the current value in the same state and setting them together. Regardless of the data types or how the next value is created, you'll always have access to the previous value in the set function. In the word example, you could just return [previousWord, newWord] from the set function, no matter where newWord comes from.
@agent.whiskeyy
@agent.whiskeyy 6 күн бұрын
This is the same as donig it "the boring way" aka storing an extra state just here u store it in an array of 1 state instead of 2 states, just over complicated for no reason
@krisbude9607
@krisbude9607 6 күн бұрын
@ you’re right… I read it wrong 😊
@ThugLifeModafocah
@ThugLifeModafocah 6 күн бұрын
@@agent.whiskeyy no, it's not. With this approach you have less rerendering because you don't need another one for previous being changed. You have only one that handles both.
@ShinigamiZone
@ShinigamiZone 5 күн бұрын
I really like watch in Vue (not watchEffect). Is there something similar in React?
@freedomowologba2900
@freedomowologba2900 6 күн бұрын
React has a useDeferredValue hook already. No need for the long walk around.
@zeroliuxiyuan
@zeroliuxiyuan 6 күн бұрын
usehooks's implementation sets state directly in the render function. This feels off to me...
@vvvvvvvvvwv
@vvvvvvvvvwv 5 күн бұрын
It's totally fine. You often don't need effects. Search for "You Might Not Need an Effect", there's a page for this in the React docs.
5 күн бұрын
“Keep in mind that useRef doesn’t notify you when its content changes. Mutating the .current property doesn’t cause a re-render”
@simboy
@simboy 5 күн бұрын
Which is a feature
@abdelazizlaissaoui9079
@abdelazizlaissaoui9079 6 күн бұрын
Yo7 should post a video about that React rendering process
@cristianmargineanu1458
@cristianmargineanu1458 5 күн бұрын
YOOO im crying right here, ive been doing this for at least 2 years and i work in a factory 😂
@additionaddict5524
@additionaddict5524 6 күн бұрын
fyi, the epic web bundle, not much more, includes epic react. kinda crazy that the site doesn't show this
@farzadmf
@farzadmf 6 күн бұрын
Please do a video of the rendering process 🙏
@byShameless
@byShameless 6 күн бұрын
Would running the code that uses the previous value inside the the setState be bad? If so can someone explain? example: setState((prev) => { *code with prev value*; return *new state*; })
@dave6012
@dave6012 6 күн бұрын
First Bender, then Flexo, then Fry.
@rajikkali2381
@rajikkali2381 5 күн бұрын
I'll say it again. Just use Nuxt or Vue because it truly is "The inuitive framework"
@bubkabu
@bubkabu 3 күн бұрын
which editor is that?
@KopoLPedov
@KopoLPedov 4 күн бұрын
just use single state for current and prev value or better - use class components
@edwardallenthree
@edwardallenthree 5 күн бұрын
Helpful video.
@LA-fb9bf
@LA-fb9bf 5 күн бұрын
What is vue.js doing here?
@O_Eduardo
@O_Eduardo 4 күн бұрын
This is one of the reasons I’ve never liked React. Honestly, I wasn’t a fan of its design from the very beginning. I’m eagerly waiting for better solutions to gain more traction-it feels like React’s time has passed. It hasn’t aged well. React developers might stick with it for so long they’ll never realize they didn’t need to go through all this complexity.
@roguesherlock
@roguesherlock 6 күн бұрын
I usually just have an array to keep track of current and previous, ```tsx export default function usePrevious(current: T) { const [state, setState] = useState([null, current]) // [prev, current] if (state[1] !== current) { setState([state[1] ?? null, current]) } return state[0] } ```
@yanidoesit
@yanidoesit 5 күн бұрын
You might like React as a developer but I fricken hate it as a user living on an island where 4G with congestion is as good as it get. Have you seen how Facebook or React app work when you have a crappy internet connection? It's hell! It times out before hydration is complete. Or even just fails to hydrate even the top post. What makes it easy for developers isn't always a solution users like.
@dbarnesdigital
@dbarnesdigital 5 күн бұрын
Hydration is terrible. If a framework uses hydration they blew it.
@iamNATFAN
@iamNATFAN 3 күн бұрын
honestly, this video just turns me off react more. why do i need to learn all of this (seemingly) arbitrary framework logic in order to not footgun myself. at least with vanilla js and regular dom updates, you know what you're getting imo
@FatahChan
@FatahChan 6 күн бұрын
I got featured in a theo video
@polski003
@polski003 5 күн бұрын
Nice
@codedusting
@codedusting 6 күн бұрын
reactnode 19 nextjs 15 failing during build because of some type error in react node. Also doesn't recognise the async components
@kingsleykelechionwuchekwa7508
@kingsleykelechionwuchekwa7508 6 күн бұрын
feels good to be first
@cherishkansara7851
@cherishkansara7851 6 күн бұрын
Yup
@shwinm
@shwinm 6 күн бұрын
Is this not an extremely obvious case for useReducer???
@cathrerinezetadrones3169
@cathrerinezetadrones3169 5 күн бұрын
Gross
Docker Image BEST Practices - From 1.2GB to 10MB
7:15
Better Stack
Рет қаралды 69 М.
How React Query Won
34:52
Theo - t3․gg
Рет қаралды 86 М.
Tuna 🍣 ​⁠@patrickzeinali ​⁠@ChefRush
00:48
albert_cancook
Рет қаралды 106 МЛН
How many people are in the changing room? #devil #lilith #funny #shorts
00:39
coco在求救? #小丑 #天使 #shorts
00:29
好人小丑
Рет қаралды 98 МЛН
The Most Important Rule for Clean Code in React
16:52
Cosden Solutions
Рет қаралды 22 М.
7 Design Patterns EVERY Developer Should Know
23:09
ForrestKnight
Рет қаралды 80 М.
Flutter Workshop - GDGC 2024
53:47
UCSC GDSC
Рет қаралды 24
This Video is AI Generated! SORA Review
16:41
Marques Brownlee
Рет қаралды 2,9 МЛН
The fastest website ever?
30:48
Theo - t3․gg
Рет қаралды 158 М.
I Created The Best AI Tool Ever
9:12
ThePrimeTime
Рет қаралды 100 М.
My Initial Impresson Of Go
12:39
TheVimeagen
Рет қаралды 105 М.
AI is not Designed for You
8:29
No Boilerplate
Рет қаралды 168 М.
Why Everyone Loves Zustand
29:27
Theo - t3․gg
Рет қаралды 111 М.
Why I Cant Stand IDE's After Using VIM | Prime Reacts
17:51
ThePrimeTime
Рет қаралды 393 М.