setState doesnt seem to update the state [duplicate] - javascript

This question already has answers here:
Why does calling react setState method not mutate the state immediately?
(9 answers)
Closed 5 years ago.
onSelectedRow(user, clickEvent){
const state = this.state;
this.state['userId'] = clickEvent.target.getAttribute(user['mta:UserId']);
this.setState(state);
console.log(user['mta:UserId']);
console.log(this.state);
}
Okay, so when I click a table-cell in my app this function gets called.
The point of it is to take the users UserId and set the state. This UserId is later on passed down to a child component and used to get specific information. The problem is that I get the correct data in the first console.log but when I then log this.
state the userId is still null for some reason. Anyone had similiar problems?

It's most probably because you're not updating the const state, but instead trying to mutate the state itself.
Also, you don't have to make a copy of a state. You can update just the field you want to update like this:
onSelectedRow(user, clickEvent) {
this.setState({
userId: clickEvent.target.getAttribute(user['mta:UserId'])
}, () => { console.log(this.state.userId) });
console.log(user['mta:UserId']);
}
Also, your console.log won't read immediate change in the state as setState is an async action.
If you really want to read it you can pass the callback to the setState which fill fire right after the state is updated, or use React's lifecycle method componentDidUpdate().

Related

Problems setting useState inside onClick handler [duplicate]

This question already has answers here:
Why does calling react setState method not mutate the state immediately?
(9 answers)
How does JavaScript mechanism behind react hooks work?
(2 answers)
Closed 3 years ago.
I am using useState hook inside onClick handler to change and track the focus state. I set it to false initially and then change it to true and false several times in the handler. After each change, I do console.log(focus) and I expect it to be respective to the changes made.
function App() {
const [focus, setFocus] = useState(false);
return (
<div
className="App"
onClick={() => {
console.log(focus);
setFocus(true);
console.log(focus);
setFocus(false);
console.log(focus);
}}
>
<h1>App</h1>
</div>
);
}
In my case, in this code snippet, I expect to see in console false, true and then false again, but I see all of them false.
Why does it happen? I feel I am missing something quite fundamental here.
When you set the state, the component will be re-rendered. State changes are not synchronous in nature. Try adding a console.log below your useState line and you'll see that it gets called every time you set the focus because the entire component is re-rendered.

How to use updated state value above render function?

I think it might be silly question to ask but trust me I am stuck to find an answer . Actually , I am trying to access updated state value in class function above render function but I am not getting updated value . when I console value in render function I got updated value . Could someone please help me how to access updated value .
Thanks
Code
fetchAgents = e => {
this.setState({
value: e.target.value
});
};
fetchFilteredInventories = e => {
axios
.get(`/api/reports/agents/?branch=${this.state.value}`)
.then(response => {
this.setState({
agents: response.data
});
});
};
when I try to access updated state value in fetchFilteredInventories I am getting null value . Could someone help me to achieve my goal
setState is asynchronous. When you console.log after setState, the state is not changed yet, it is in the process of changing. Try this
this.setState({
value : e.target.value
},()=>console.log(value));
You will see the value is updated. setState allows a callback function as arguement. So use the callback function to use the updated state value.
Read the docs for further info: https://reactjs.org/docs/state-and-lifecycle.html#using-state-correctly
It depends on where you are calling your fetchFilteredInventories function.
After a state update in a React component certain lifecycle hooks get called, such as componentWillUpdate, componentDidUpdate. you can read about them in React docs here State and Lifecycle.Make sure you are calling your API call function at the right moment.If you can, put your whole component code here for better answers.
Try This
axios.get(`/api/reports/agents/?branch=${this.state.value}`).then(function(response) {
this.setState({
agents: response.data
});
}.bind(this));

modify a setState from the data retrieved via a link [duplicate]

This question already has answers here:
setState doesn't update the state immediately [duplicate]
(15 answers)
React slow setState at console.log
(1 answer)
Closed 3 years ago.
Hello everybody
I'm a young beginner in programmtion. I'm trying to recover data from a Link to another component. Everything works except just put this recovered data in a state object with setState. I think I don't know evrything possible about setState but I'm quite lost.
I have this link which send the data "Command_ID" :
<Link to={`/produits/${Command_ID}`} className="item" params={{ Command_ID: {Command_ID}}}>
And as expected, I recover data like this and I recall it "order_id" :
state = {orderId: null};
componentDidMount() {
const order_id = this.props.match.params;
console.log(order_id);
this.setState({orderID: order_id});
console.log(this.state.orderID);
}
I can see in my console.log(order_id) the right number recover in the link part with the good "Command_ID". But when I try to put it with the setState and see in my console if it works, I just have a value of undefined for this.state.orderID
Thank you for your help :)
setState is async method , to execute something after the state is set you can pass function as second parameter for setState
this.setState({orderID: order_id}, () => console.log(this.state.orderId));

Calling setState with nested object does not update state correctly

I have a React component that maintains state for several child components. Via componentDidMount() I am calling this function in the parent component from the child components:
change = (fieldset, field, data) => {
this.setState({
[fieldset]: {
...this.state[fieldset],
[field]: data,
}
})
}
Think form/fieldset/field for the usage pattern, but with fields calling the above function.
The problem I'm having is that I believe I'm confusing React by calling this function so many times in quick succession, because state is not updated for all but one or two items.
I've tried using Object.assign() to avoid mutating state, but for the most part state has not updated correctly even at the point where I begin to read current start.
Is this against React best practices? Is there a better way for child components to call setState in a parent component?
Since the way you update the state depends on the state itself you need to use a function instead of an object.
change = (fieldset, field, data) => {
this.setState(prevState => ({
[fieldset]: {
...prevState[fieldset],
[field]: data,
}
}))
}
Functions will be applied one after another. So you wont override any pending changes.
From docs
this.setState({quantity: this.state.quantity + 1})
this.setState({quantity: this.state.quantity + 1})
Subsequent calls will override values from previous calls in the same
cycle, so the quantity will only be incremented once. If the next
state depends on the previous state, we recommend using the updater
function form, instead.

ComponentDidUpdate SetState ReactJS Infinite loop

Even though there are many questions with the same subject line, I could not get an answer for my problem.
Problem
I have a select dropdown. On click of which, I call an Api which fetches some key values. I consider this set of key value input fields as a component. So each and every time onChange of my select drop-down, I have used lifecycle methods to handle API Calls. Also, I record these input key values and send back their state to parent component.
According to ReactJS lifecycle methods:
I use
componentDidMount
To call the API for the first time after initial render. This works.
componentDidUpdate
To call the API for subsequent API calls on select drop-down change. But here is the problem. When I try to update the state of input fields the program falls into an infinite loop and hence there are infinite API calls. I am pretty sure after debugging that the problem is with setState(), But I couldnt find the best way to handle states in componentDidUpdate method.
This link exactly replicates my problem but i want a standardized solution
Hope this is clear.
Thanks for the help in advance!
This is spelled out pretty clearly in the docs:
componentDidUpdate(prevProps) {
// Typical usage (don't forget to compare props):
if (this.props.userID !== prevProps.userID) {
this.fetchData(this.props.userID);
}
}
You may call setState() immediately in componentDidUpdate() but note
that it must be wrapped in a condition like in the example above, or
you’ll cause an infinite loop.
You can use setState() within componentDidUpdate(). But you have to use the condition for that. Otherwise, it get infinite loop.
As the example,
componentDidUpdate(){
if(this.props.id !== this.state.id) {
this.setState({
id: this.props.id
});
}
}
This happens because setState triggers a call to componentDidUpdate.
When componentDidUpdate is called, setState does not check whether or not state change has occurred. It simply calls componentDidUpdate again and again, which leads to stackoverflow.
class Component extends React.Component{
constructor(props){
super(props);
this.state = {changeState: false}
}
componentDidMount(){
this.setState({changeState: true});
}
componentDidUpdate(){
this.setState({changeState: false});
}
}
Here, first changeState is set to false in constructor, and then componentDidMount is triggered, which sets state of changeState to true. This state change triggers componentDidUpdate, which sets the state of changeState again to true. This triggers componentDidUpdate again and again.
You have to check the real difference between two state objects.
Below you can find my solution, My state object has movies, which is an array of objects. I edited and movie and then comparing these two arrays.
async componentDidUpdate(prevProps, prevState) {
if (prevState.movies.filter (e => this.state.movies.includes(e))) {
const response = await axios.get("http://localhost:3002/movies");
this.setState({ movies: response.data })
}
}
Yes you cannot setState() inside componentDidUpdate it would lead to infinite loop.Instead you can call a function onChange event and change the state there.

Categories