0

I have a state configured in React that is an array of objects:

state = {
        metric: [{name: "", type:"", reward: false}],
    }

I want the reward attribute to be updated (from false-> true or true->false) when a particular checkbox is checked, which I wrote an onSelectedChange function that uses a particular index in the array as a parameter:

onSelectedChange = (idx) => {
        this.setState((prevState) => ({
            metric:{
                [idx]: {
                    ...prevState.metric[idx],
                    reward: !prevState.metric[idx].reward
                }
            }
        }))
    }

But after this function runs, something must have messed up the state configuration because a later function that uses metric.map(val, idx) fails.

Example of what I expect after the function call:

Before:

state = {
        metric: [{name: "latency1", type:"counter", reward: false},
                 {name: "latency2", type:"counter", reward: false}]
    }

After calling onSelectedChange(1):

state = {
        metric: [{name: "latency1", type:"counter", reward: false},
                 {name: "latency2", type:"counter", reward: true}]
        }
2
  • If you want to affect the first object. You should use it this way. onSelectedChange(0) Commented Mar 25, 2020 at 22:27
  • @Minan Right, but my example is affecting the 2nd element in the metric array, which has index 1. Commented Mar 25, 2020 at 22:32

2 Answers 2

3

You are creating metric as an array but assigning to an object in your change function. If you want to change state by the index of the item in the array, you can use spread operator to copy your state and assign it to a new variable, update it and pass this to setState in your onSelectedChange function. e.g:

let metric = [...this.state.metric];
metric[idx] = { ...metric[idx], reward: true };
this.setState({
  metric
});
Sign up to request clarification or add additional context in comments.

3 Comments

How would you use prevState in this case to update the reward attribute? Since I would want to swap between true and false with every click on the checkbox.
you can toggle the reward value with: metric[idx] = { ...metric[idx], reward: !metric[idx].reward};
After learning a bit more about JS and React in general, this answer is much more efficient than my previously accepted one. Thank you!
0

Try doing this:

onSelectedChange = (idx) => {

let newMetricArr = this.state.metric.map((metric,i) => {
    if (i === idx) {
        return {
            ...metric,
            reward: !metric.reward
        }
    }
    return metric;
})

this.setState({metric: newMetricArr})
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.