1

I'm trying to add a state variable to another state variable.

Why am I doing this?

I'm using Firebase as a database and storing my (relatively small amount of) data through state in React. I could use different variables for each "set" of data, but I'm trying to see if it is possible using a single variable.

So, I'm creating different state variables (here: child1 and child2), and at the end storing them, or rather pushing them into another state variable (here: parent), and finally storing the state parent using firebase only.

Here's what I have tried so far:

constructor() {
    super();

    this.addMember = this.addMember.bind(this);
    this.state = {
        parent: [],
        child1: [],
        child2: []
    };

    // const child1 = [0], child2 = [0];

    // Tried using the above and below methods as well!

    // const child1 = [];
    // const child2 = [];
}


addMember(member) { // member has a property of name

    switch (member.name) {
        case `child1`:
            this.child1 = [...this.child1].push(member)  // this throws an error as it is unable to access "undefined"
            break;
        case `child2`:
            this.setState({
                child2: [...this.state.child2, member]
            })
            break; 
        default:
            throw alert("something is reeeeeeally wrong")
            // break;

    }

    let counter = {...this.state.parent}
    counter[`${member.name}`].push(this.state.child2);
    this.setState({ parent: counter})


}

The above code uses examples from other answers, which show how to store and access data within a nested object in a state:

React.js - What is the best way to add a value to an array in state

How to set a nested state in React

Accessing class variable declared in constructor in other parts of the app (React)

Sreetam Das
  • 3,226
  • 2
  • 22
  • 36
  • Your code is a bit confusing to me but if you are trying to add items to an array to store it later in the state it's a better practice to build the entire array in a local variable and then set the state once instead of do a push and setState for each item. – Rodius Dec 13 '17 at 16:14
  • @Rodius hadn't thought of it that way, I'll definitely try it that way. But I still want to know if what I am trying to accomplish is *possible* or not. – Sreetam Das Dec 13 '17 at 16:17
  • Is it required for `parent` to be an array? – T Porter Dec 13 '17 at 16:50
  • @TPorter Not really, anything that works really – Sreetam Das Dec 13 '17 at 16:56

2 Answers2

1

It isn't advisable to store a state variable that is derivable directly from state or props. Instead you could store child1 and child2 as class variables and set parent state from them. Also what you are trying to do will not actually work out, since setState is async and you would need to handle it a little differently

An example of using class variable

constructor() {
    super();

    this.addMember = this.addMember.bind(this);
    this.state = {
        parent: []
    };

    this.child1 = [];
    this.child2 = [];
}


addMember(member) { // member has a property of name

    switch (member.name) {
        case `child1`:
            this.child1 = [...this.child1, member]  
            break;
        case `child2`:
            this.child2: [...this.child2, member]
            break; 
        default:
            throw alert("something is reeeeeeally wrong")
            // break;

    }

    let counter = {...this.state.parent}
    counter[`${member.name}`].push(this.child2);
    this.setState({ parent: counter})
}
Shubham Khatri
  • 270,417
  • 55
  • 406
  • 400
  • Could you share a source where I could read up on how I could handle it differently? – Sreetam Das Dec 13 '17 at 18:09
  • handling it differently meaning updating the state also into the switch component for parent. Also when updating state based on previous one, use the prevState updater function, check this https://stackoverflow.com/questions/42197819/cant-update-a-components-state-inside-a-callback-function/42198053#42198053 – Shubham Khatri Dec 13 '17 at 18:13
  • ah. Thanks a lot! btw, what's the difference between declaring the variables as `this.varname` and `const varname`, as I had perviously? – Sreetam Das Dec 14 '17 at 07:14
  • const varname has a scope limited to the enclosing `{}`, and then you write using `this.varname`, it has a scoped to your entire class – Shubham Khatri Dec 14 '17 at 07:24
  • Hey, I just tried your code, and the last but one line still returns the error `TypeError: Cannot read property 'push' of undefined`. Any way to fix that? – Sreetam Das Dec 14 '17 at 08:11
  • Sorry for the the mistake, it should be `let counter = [...this.state.parent]` updated that in the code – Shubham Khatri Dec 14 '17 at 08:14
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/161166/discussion-between-thedarkknight-and-shubham-khatri). – Sreetam Das Dec 14 '17 at 08:24
1

If the shape of the parent object is guaranteed (meaning something like child3 will never be added), the following would work

state = {
  parent: {
    child1: [],
    child2: []
  }
}

addMember(member) {

  this.setState(prevState => ({
    parent: prevState.parent[member.name].push(member);
  }));
  
}
T Porter
  • 1,162
  • 7
  • 15