0

I have a state variable in react as:

this.state = {
    formStatus : {
        approved : true,
        rejected : true,
        pending  : true
    }
}

and a dynamic array whose value can contain either one or all of these values

appliedFilters = ['approved', 'rejected', 'pending']

Now What I want to do is set my state keys to false if the array doesn't contain them.

For example, if the array is ['approved', 'rejected'] then my state should be set as:

this.state = {
    formStatus : {
        approved : true,
        rejected : true,
        pending  : false
    }
}

I want to do it using ES6 map() if possible.

I have done something like this but it is not working:

appliedFilters.map(filter => {
    this.setState(prevState => ({
        formStatus: prevState.formStatus.map(
            status => (status === filter) ? true : false
        )
    }))
})

3 Answers 3

3

You can't build an object using a map. And you don't want forEach because there's no need for mutation here. Maps work on (and return) collections. You should use reduce.

const appliedFilters = ['approved', 'rejected']

const state = ['approved', 'rejected', 'pending'].reduce((newState, item) => ({
    ...newState,
    [item]: appliedFilters.includes(item)
}), {});

this.setState(state);
Sign up to request clarification or add additional context in comments.

5 Comments

this actually doesn't work properly. setting state of invalid structure here.. fix it by this.setState({ formStatus: state })
i figured that out...... however can you explain to me the purpose of empty {} in the reduce function you used.
It's called 'accumulator'. Read more about it here: developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/…
@streletss i think you meant initial value. Initialize state with empty object
Yes it's the initial value, it's what newState will be the first time the reduce callback is executed. It's an object here, but if you were, say, adding numbers together in a reducer, the initial value might just be 0, and you keep adding to it and returning the new accumulated value.
1

It's not possible Array.prototype.map, because the map function return new Array()....

Try do this.

const allFilters = ['approved', 'rejected', 'pending'];
const appliedFilters = ['approved', 'rejected'];

const newState = {};
allFilters.forEach(filter => {
    newState[filter] = appliedFilters.includes(filter);
});

// use!!!
newState;

Comments

1
  1. You can't call .map on prevState.formStatus. It's an object, not array.
  2. Avoid calling this.setState on every iteration of .map.

You could consider simply doing this:

this.setState(prevState => ({
  formStatus: Object
    .keys(prevState.formStatus)
    .reduce((acc, stat) => ({ ...acc, [stat]: appliedFilters.includes(stat) }), {}) 
}))

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.