when i call this.setState in my code it seems to do nothing at all
this.setState({array:pre.array},()=>{console.log("setState")})
i can't even see the log from the call back function here is my code
class Watch extends React.Component{
constructor(pre) {
super(pre);
this.state = { color: "green" }
this.setState(() => {
return {array:newarray}
}, console.log("setState works"))
p.s:i have tried to put setState in onClick function, in componentDidMount(),componentDidUpdate() still dosent work with no error
It seems like when using setState callback system, the first parameter (updater) needed to be in the form of a function as well. So you can try something like:
onEditText=(value)=>{
this.setState((state, props)=>{
return {text: value}
}, this.onTextEdited);
}
onTextEdited=()=>{
//this will be printed with the updated value
console.log('onTextEdited', this.state.text)
}
See if this helps.
Related
I have a react component useEffect hook that looks like the following. I am working with firestore. I am trying to remove a value from an array in firestore when the component unmounts. However, the value is not getting removed. I tried running the firestore query in the cleanup function independently to see if that query was the problem, but it's working fine independently. It's just not getting executed when it's inside the cleanup function. I THINK the problem is that my cleanup function at the end of the useEffect hook is not getting called when the component unmounts(for example when I close the window). does anyone know what I may be doing wrong? Thank you for your help in advance
useEffect(() => {
.......
return () => {
fire.firestore().collection("ActiveUsers").doc(utilvar.teacherID).get().then((snapshot) => {
var docref = snapshot.ref;
return docref.update({
active_users : fieldValue.arrayRemove({id: currentUser.uid, name: displayName})
})
})
};
}, []);
From my observation. utilvar.teacherID might not be ready as at the time your component got mounted.
So you may want to add it to the dependable array.
Your useEffect should therefore look something like this :
useEffect(() => {
.......
return () => {
fire.firestore().collection("ActiveUsers").doc(utilvar.teacherID).get().then((snapshot) => {
if(snapshot.exist){
return snapshot.ref.update({
active_users : fieldValue.arrayRemove({id: currentUser.uid, name: displayName})
}).catch(err=>err);
})
};
}, [utilvar.teacherID]);
I added the catch as it a promise being returned. It must be handled appropriately irrespective of where it's being used.
When using a callback from a child to app.js, the callback function in app.js sets the state for an element.
In the same child-function, on the next line, the function accesses this state, which is passed along as a prop.
Is there a way to make sure that this next line executes with the updated state already? If not, whats a better way to implement this?
Child Component
function handleCountrySelected(selected) {
let selectedValues = {
countries: selected,
planningGroups: null,
};
onFilterChange(selectedValues); // changes selectedFilters.country via callback
console.log(selectedFilters.countries); // still old state. selectedFilters is a prop from apps.state. Here it is still showing the old value
filters_changed();
autoApply && applyFilter(); // applyFilter fails because its accessing old state, still.
}
App.js
updateSelectedFilters(selectedValues) {
this.setState({
selectedFilters: {
...this.state.selectedFilters,
...selectedValues
}
}
...
<NavbarTopFilters onApplyFilters={this.onApplyFilters}
selectedFilters={this.state.selectedFilters}
onFilterChange={this.updateSelectedFilters}
/>
setState is an async function. You need to pass in the rest of the lines as a callback.
function updateSelectedFilters(selectedValues, callback) {
this.setState({selectedFilters: {...}}, callback);
...
}
onFilterChange(selectedValues, () => { console.log(...) });
Heres a function from my react app:
handleSubmit(evt) {
evt.preventDefault();
this.setState({
width: "",
height: "",
color: ""
});
console.log(this.state)
};
In my input, I set the value of input to the width, height and color. this handleSubmit function is happens when a form in filled.
But I have set the state via setState before the console.log line. So this will replace the values from the form, before the console.log is called. I should get
{width :" ", height :" ", color :" "}
But instead, I get the value that was set by the input. But it seems like setState is only working when the full function is done, not before the log. Why?
But it seems like setState is only working when the full function is done, not before the log. Why?
setState doesn't change the state immediately. Ref: https://reactjs.org/docs/react-component.html#setstate
If you want to do something right after the state change, use a callback function.
handleSubmit(evt) {
evt.preventDefault();
this.setState({
width: "",
height: "",
color: ""
}, () => {
console.log(this.state)
});
};
You can use functional setState rather than passing an object. Instead you can pass a function to setState which takes the current state and props as arguments, this function returns an object which will be merged into the old state.
For example,
this.setState((state, props) => {
return {
counter: state.counter + 1
}
});
Calls to setState get queued and then executed in the order they were called. When they are executed the function receives the latest state instead of receiving old state.
The thing is, that I use setState to update state.n and state.data. I want to call setState onClick, using handler. After calling setState, I perform a callback console.log to watch the changed state properties, but only state.data is changed, not state.n.
handler(e) {
this.setState((state) => {
let arr = state.data;
arr.push(fakeTableData[state.n+1]);
this.setState({n: state.n+1, data: arr});
}, console.log.bind(null, this.state.n));
}
After one handler used, I expect to see state.n incremented, but I had only state.data changed, not state.n. And I recieve a warning, like this: "Warning: An update (setState, replaceState, or forceUpdate) was scheduled from inside an update function. Update functions should be pure, with zero side-effects. Consider using componentDidUpdate or a callback." I've read a tutorial on the main react site, but there not enough info.
let's try let arr = [...state.data]
You should not use setState inside function that sets state. That is why you got an error. Instead you should return state. Try this:
handler = (e) => {
this.setState((state) => {
let arr = state.data;
arr.push(fakeTableData[state.n+1]);
return {n: state.n+1, data: arr};
}, () => { console.log(this.state.n) });
}
In _onChange method, I wait for a change in this.state.name. On the change _updateArticle method is called:
_onChange() {
var team = this.getTeamState();
this.setState({name: team});
console.log(this.state.name); //"Boston Celtics" //this should have changed but it didn't
this.unbind("articles");
this._updateArticle();
},
then in _updateArticle a new reference is created using this new state.
_updateArticle(team) {
var teamRef = new Firebase(this.props.baseUrl + team + "/results");
console.log(this.state.team); // "Boston Celtics" //this should have been new but its not
this.bindAsArray(teamRef, 'articles');
},
In render method however just to check the state I put console.log to check. In render, this.state.name has been updated properly. My question is why is this.state different outside of render function?.
As per the API docs:
setState() does not immediately mutate this.state but creates a pending state transition. Accessing this.state after calling this method can potentially return the existing value.
If you really want to access state right after calling setState, use the callback parameter in the setState method:
setState(function|object nextState[, function callback])
So your code should look like:
_onChange() {
var team = this.getTeamState();
this.setState({name: team}, function() {
console.log(this.state.name);
this.unbind("articles");
this._updateArticle(this.state.team);
});
}
Hope this helps.