Sometimes setState doesnt working all by itself and i am adding small timeouts to do it.
My first question is;
1-) Why setState sometimes doesnt working without a delay?
2-) Is it correct to add setTimeout? - And its small amount of delay like 10 ms, its nothing, but it makes my code to work and state to update.
When i was coding in Angular1, we were using $timeout sometimes for scope to apply this changes. But it was okay to do so, in React i am not sure about this.
Any help would be appreciated, thanks.
It sounds like you're attempting to call setState in a render. This is bad because render occurs immediately following state updates. It causes a render loop. You should not use a setTimeout to do this either. That causes React to stop warning you because it can no longer detect the issue. This will cause large random bugs in your app.
Your symptoms are a sign that you need to push the state up into container components.
The reason why there is a delay in setting the state is that 3 lifecycle method of ReactJS are called while setting the state.
setTimeout is a way to get the current value of the state which has just been set, However another alternative would be that you can create a callback function inside the setState to get the current value.
Use of setTimeout must be always be avoided until and unless there is no other alternative.
example:
this.setState({show:true},()=>{console.log(this.state.show)})
Related
I have a very simple component that fetches data and do some easy computation. Every time the page refreshes the component renders, the value will change. I have also tried clearing the cache thinking it might be an issue but it didn't solve the problem. Thank you for your help!
I have tried removing and I get a warning with a message suggesting to add difference but even without it, it still behaves the same on every single render. I use difference value like this
I have put the code on Sandbox to make easier to debug. Same problem still occurs on every other page refresh.
https://codesandbox.io/s/agitated-cdn-q3gju?file=/src/Card.js
Each state change generates the component rendering. You are listening to the "difference" variable change and changing it again with setDifference, creating a loop.
This
useEffect(()=>{
setState(something)
},[state])
Use
useEffect(()=>{
setState(something)
},[])
I have a couple set states on providers that trigger a bunch of effects throughout my react app. They happen back to back in a hook. The second set state has some effects that it triggers that need make sure that the first hook fully propagated through the app. Currently the first one has not made all the required changes so some functionality triggered by the second causing weird behavior. How do you ensure that the second one only happens after the first is fully propagated?
setSomeStateValue(x);
setValueToTriggersEffectsThatRelyOnUpdatesFromTheOther(y);
Here are some thing I have done that work but have their issues:
1.) settimeout(...,0)
setSomeStateValue(x);
setTimeout(otherSetState,0);
This pushes the second one to a subsequent batch. I like this one because it doesn't involve adding extra code to watch other state variables that the code maybe shouldn't be concerned with, but it does seem a little black magicy and could possibly cause hard to debug issues.
2.) monitor the stuff i need set before calling the second set state
This one seems a little more readable but involves importing and watching things that might not make sense that they belong in the related code. Basically adding a useEffect that watches everything I need set before the second call happens. Also if something changes in regards to what is needed to have the second call ready then this code will have to change as well where as the first solution should not require an update.
Both of these work but have their fallbacks. I would like to refactor the second call to account for these issues but that would be too large of a refactor at this point too make it a feasible option. Is there a native way to ensure this or another strategy here that I am missing? And if not, which one of the above solutions is better?
In such situations where a setState is dependent on a previous setState or a specific state of the component, you can potentially do two things. First,
use the second argument of setState. Here, callback is only invoked once setState is done updating the state. Hence you can get the desired synchronous behaviour.
setState(updater, [callback])
Use componentDidUpdate lifecycle method ( For Hooks, it would be just another useEffect ). If you don't want to have complex setStates in your component, simply have an effect with a dependency on the needed state and do your operations there
React.useEffect(() => {
if( desired_state){
secondSetState()
},
[ desired_state ]
}
I am trying to understand more about React, so I did some very simple test.
I know my test is NOT react way of doing things, but since it is still Javascript, I am just testing how everything is working for curiosity.
I declare a variable outside of react component, and every time the function component renders it will add 1 to the variable.
I activate the re-render by using a button, the button will activate an increase function then use a setState thus cause the component to re-render.
What I notice is the a variable is adding 1 twice, I put 2 console.log before and after it to monitor it. I can see there is one execution of adding, but where it the other adding coming from? The afteradding after rendering should be the same of next round's value before adding.
See the code, thanks in advance for any deeper understanding.
Thanks for the help, after removing the strictmode, app is behaving normally now.
I've been search for quite a while, but i wasn't able to find a good solution to this.
I have to trigger a function/event, as soon as the DOM of a component finished rendering.
I need to access the height of the component, so ngAfterViewInit won't work, as that is called before the DOM is rendered.
I tried ngAfterViewChecked, but this gets called multiple times. As the function that gets executed is part of a wrapper-app, i have no access to that either, and i absolutely need to make sure it only gets fired once. I was thinking about using ngAfterViewChecked with some sort of debounce, but this feels (and probably is) wrong.
The alternative would be to trigger a function from the template, when the ngFor loop reaches the last item. But again, that just feels wrong.
Any input is appreciated
I got around this issue by using ngAfterViewChecked. On every check, i get the scrollHeight of the components body. Before it renders, it will be 0, so checking if there's been a change on the scrollHeight attribute, works for my use case.
Thanks for all the comments, that actually made me think of this solution
First, thank you for your patience and expertise. Without you, I'd be mopping floors. From Linus Torvalds to DHH to you-- Awesome.
So I have a question duplicate ( answered here-- Why calling setState method doesn't mutate the state immediately? )
I have a 42 radio group form that calls setState for each choice. The above solution says the calls are asynchronous and cause the components to reload. I don't [think I] need to do that. How would you store in memory-- session, cookie -- or something that doesn't cause a repaint until the user submits the form? Sorry if this is another duplicate. I'm slow that way.
Again, thanks.
Not "repainting" the page is not how react works. I am constantly "repainting" the screen as the user interacts with the page I work on.
You want to use setState because if the user keeps clicking around you want to be able to keep updating and tracking what they did, so each update doesn't overwrite. The asynchronous update is beneficial in that you get a copy of the state at the exact moment the user fired off the actions, which ensures you don't end up in a funky state if a user updates a few things at once.
This might be an "asynchronous" update but it feels like it happens immediately and triggers the components to update themselves with the new information (aka repainting)