Update array object by specific index - reactjs

How can I update groceries item(set completed to True) in my toggleGroceryCompleteness method?
I tried this.setState({groceries[groceryIndex]:{completed:true});
constructor(props) {
super(props);
this.state = {
groceries: [
{
name: "Apples",
completed: false
}
],
newGroceryName: ""
};
toggleGroceryCompleteness(groceryIndex) {
console.log(groceryIndex);
console.log(this.state.groceries[groceryIndex]);
}

Since you're editing the value of a previously set state, you should use this definition of setState
this.setState((prevState, props) => {
const newGroceries = prevState.groceries.slice()
newGroceries[groceryIndex].completed = true
return { ...prevState, groceries: newGroceries }
})
This takes the value of the groceries state array from before the setState call and assigns it to a new variable to be modified, accessing the given index and sets the completed property to true. Then returns a new object/state containing everything from the previous state value but a modified groceries property which is the new modified version.

Related

How to setState from function parameter in React [duplicate]

This question already has answers here:
React this.setState is not a function
(16 answers)
Closed 3 years ago.
I am passing the name and value to handleChange function from child component.
Now I want to set the state to the value that matches the provided name.
But I do not know how to set it.
I tried this way(but it gives error - 'this.setState is not a function') :
class ParentComponent extends Component {
constructor(props) {
super(props);
this.myRef = React.createRef();
this.state = {
loanAmount: 348600.48,
numberOfYears: 70,
}
handleChange(name, value) {
this.setState({ name: value },() => {
this.financeCalcualte();
});
}
The code of the child component is:
onChange = (event) => {
const {name, rawValue} = event.target;
this.props.handleChange(name, rawValue)
}
What is the correct syntax to set it?
In order to use this in a callback function, as told in the comments you have to bind it in the constructor or use an arrow function.
Also, since your name is a variable, you can't update your state like:
this.setState({ name: value }
because this creates a name property in your state, does not update the state variable which has the name as your incoming variable. So, you should use a computed property.
handleChange = (name, value) =>
this.setState({ [name]: value }, () => this.financeCalcualte());
It seems like you are looking for computed property name
handleChange(name, value) {
this.setState({ [name]: value },() => {
this.financeCalcualte();
});
}
If you have this function in a Class based component then you can update your current function to an arrow function like below.
handleChange = (name, value) => {
this.setState({ name: value },() => {
this.financeCalcualte();
});
}
The thing is you are accessing this without a context being given.
Another way can be you bind this to the function. Below is the example to do it the other way inside your constructor.
constructor(props) {
super(props);
this.handleChange = this.handleChange.bind(this);
// Other code ....
}
EDIT
Also as mentioned in other answer and comments you have to use computed property name, you can not just use a variable name directly and set it to another variable.
this.setState({[name]:value})

How to Setstate array in React Native

How to set state field in array.
Below is my code:
constructor() {
super();
arrayCheck: [
isCheck = false
]
}
I want to get isCheck and then set state to true.
How can I set it?
Below is my function setState
onCheckBoxChange(isCheck, index, item) {
this.setState({........});
}
If you really want to update a state variable using array you can try this.
First, you need an array of object in state variable and update it like this
constructor () {
super();
this.state = {
arrayCheck: [
{ isCheck : false }
]
}
}
then update its value like this
onCheckBoxChange(isCheck, index, item) {
let arrayCheck = [...this.state.arrayCheck]
arrayCheck[0].isCheck = true
this.setState({
arrayCheck
})
}
First you need arrayCheck to be in the state object:
this.state = {
arrayCheck = [...]
}
Second, I would suggest using an object rather than an array. In array you can only access the index that holds the value.
With an object you may do something like:
constructor () {
super();
this.state = {
objectChecks: { // my also just set isCheck on the state
isCheck: false
}
}
}
And then when you want to change it:
this.setState({objectChecks: {isCheck: true}})
Hope it helps

ReactJS change value of nested state

I have a form in which inputs have an initial value (which is different for each input). I set the value by saving the data in a state array, like so:
function createData(header, content) {
id += 1;
return {header, content, id};
}
class ExampleForm extends React.Component {
constructor(props) {
super(props);
this.state = {
data : [
createData( Header1, Content1),
createData( Header2, Content2),
createData( Header3, Content3),
]
}
Once the user startes typing something into the input field, I need to change the value of the state in in question in the corresponding array, however, I'm having trouble correctly targeting said state.
This is what I'm currently doing:
handleInputChange = (value, target) => {
const selectedArray = {...this.state.data[target]};
selArray.header = value;
this.setState(selArray);
};
}
(Note: value is the new value, target is the index)
However, it doesn't work because when I console.log() the new value, it still returns the old value.
I also read several other questions on here (with the help of with I wrote the code for what I'm doing right now in the function that changes the value), however, that did not work.
Other questions I read include React: Update nested state? , however, I could not figure out where they got getPersonsData() from, for instance. Does anyone know what I'm doing wrong in my current code? How do I fix it?
Update the state like this:
handleInputChange = (value, target) => {
const data = [...this.state.data];
data[target].header = value;
this.setState({ data });
};
To check the updated state value, use callback method, like this:
handleInputChange = (value, target) => {
const data = [...this.state.data];
data[target].header = value;
this.setState(
{ data },
() => console.log('updated state', this.state.data)
);
};
For more details about asyn behaviour of setState check this answer: Why calling setState method doesn't mutate the state immediately?

Is Initializing state with props object causes mutation?

In my React application, one of the components needs state initialization from props.
Class ComponentA extends React.Component{
constructor(props){
this.state = {
objectA: props.objectA
}
}
someOnclickFunction(e){
let updatedObjA = this.state.objectA;
updatedObjA.value = e.target.value;
this.setState({
objectA: updatedObjA
})
}
}
In the above code snippet, props.objectA reference is copied to state. So, Am I mutating the props indirectly by updating the state?
Or setState() function will clone the object and keep new reference for the objectA?
class ComponentA extends React.Component {
constructor(props) {
super(props);
// state is null at this point, so you can't do the below.
// this.state.objectA = props.objectA
// instead, initialize the state like this:
this.state = {
objectA: props.objectA,
};
}
someOnclickFunction(e) {
// you can't set "objectA.value" like the following
// this.setState({
// objectA.value: e.target.value
// });
// you need to create a new object with your property changed, like this:
this.setState({
objectA: Object.assign({}, this.state.objectA, { value: e.target.value }),
})
}
}
This is a mistake that many beginners at react make. You can't simply update sub-properties of an object without consequences.. The following would also be wrong:
someOnclickFunction(e) {
var tmp = this.state.objectA;
// WRONG: don't do this either, you're modifying the state by doing this.
tmp.value = e.target.value;
this.setState({
objectA: tmp,
});
}
To elaborate on the correct way to do this using Object.assign.. this function takes all the parameters and merges them into the first element. So by providing a new object as the first parameter, you've created a copy of your first object with your new property.
Object.assign({}) // = {}
Object.assign({}, objectA) // = copy of objectA
Object.assign({}, objectA, { value: "newValue" }) // = copy of objectA with 'value' = 'newValue'.
Note: Object.assign() is a shallow clone, not a deep clone.

Why does it display only the last value of the array, and not the whole?

Why does it display only the last value of the array, and not the whole?.
When you update the value in the database, When you update the value in the database, it outputs all
constructor(props) {
super(props);
this.name = this.props.name;
this.state = {[this.name] : []};
}
componentDidMount() {
let cardQuantity =
firebase.database().ref("Users").child(this.name);
cardQuantity.on('value',snap => {
snap.forEach((childSnapshot)=> {
let card = {text: childSnapshot.val(), id: childSnapshot.key};
this.setState({[this.name] :[card].concat(this.state[this.name])});
});
});
}
render(){
return (
this.state[this.name].map( card => <h2 key={card.id}>{card.text}</h2>)
);
}
setState() is async so you have to use callback form of setState like below:
this.setState(prevState => ({
[this.name]: [card].concat(prevState[this.name])
}));
Demo: https://codesandbox.io/s/zrq0xxq2px
It shows 2 versions based on your code:
fixed version that is using callback form of setState and displaying the whole list
unfixed version based on your code that is showing only the last element of an array
From the official React's documentation:
If the next state depends on the previous state, we recommend using
the updater function form, instead...

Resources