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)
},[])
Related
I'm currently struggling with setting the page of a data table externally before the table data is loaded. In my application the data table page either comes from the URL or the local storage. In theory as soon as the component is created I know on which page of the table the user should end up on.
But setting the page immediately will be of no use because after the data of the table is loaded the table page is set back to 1 again. But since I usually use a computed property for keeping the table data I simply wait for changes on this and update the table page afterwards. Unfortunately this doesn't work if there is a lot of data or the data structure is more complicated the rendering takes a bit longer so my update is coming in too early.
I couldn't find any hints in the docs that this is not supported and created a github issue since it seems like a bug to me, at least judging by some contradictory data in the dev tools.
I also tried to recreate the scenario in a codepen, obviously in this case one could just wait until "loadData" is done but as I said for my application the slight delay between getting the data and it showing up in the table seems to be the issue but leads to the same result in the end.
I tried the same with the options property but couldn't see any notable difference:
:options.sync="myOptions"
Do you guys have any recommendations on how to handle this? Either any way of keeping the page after the data changes or any reliable way to update the page after the table is populated and rendered? I feel like I tried most events of the table but had no luck yet.
Thanks in advance! :)
This really seems to be a bug in vuetify. When the items are updated the page gets reset to 1 but only inside the component. The page prop never reflects that change.
A workaround would be to trigger a change of the page variable on our side. So in your example I put the following at the end of the loadData method.
const p = this.page
this.page = 1
this.$nextTick(() => {
this.page = p
})
This puts the page prop back in sync with the component and it seems like the correct page is loaded immediately, at least inside the codepen.
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
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)})