简体   繁体   中英

Set dynamic state name in React.js

I am starting my adventure with React so it is a hard time for me, however I prepared such pen for you to test. Here is a portion of code:

class App extends React.Component {
  constructor() {
    super();
    this.state = {
        settings: true,
        next: false,
    };

  }


   toggler(abc) {
     console.log(">>", abc)
     this.setState({
       next: !this.state.next
       /* {abc}: this.state.{abc} */
     }) 
     console.log(this.state.next)

   }

  render() {
    return (
      <div className="kalreg">
      <MyButton name='settings' isActive={this.state.settings} type="settings" toggle={this.toggler.bind(this)}/>
      <MyButton name='settings2' isActive={this.state.settings} type="settings" toggle={this.toggler.bind(this)}/>
      <MyButton name='next' isActive={this.state.next} type="next" toggle={this.toggler.bind(this)}/>

    </div>)
  }

}

class MyButton extends React.Component {
  constructor(props) {
    super(props);
  }

  onChangeName(){
    console.log(this.props.type)
    if ( this.props.isActive ) { console.log("this one is active"); } else { console.log("ouch! it is not active, ignoring!"); return;}
    this.props.toggle(this.props.type);
  }

  render () {
    if ( this.props.isActive ) {
      return ( <div className="button notVisible" onClick={this.onChangeName.bind(this)}>{this.props.name}</div>)
    } else {
       return ( <div className="button visible" onClick={this.onChangeName.bind(this)}>{this.props.name}</div>)
    }
  }
}

ReactDOM.render(<App />, document.getElementById("app"));

What I am trying to achieve is that when i press one of "settings" buttons (yellow) the "next" button becomes unclickable (green). There is a toggle function that every time I click settings button it turns on and off "next" button.

It works quite good, however it is just a draft of bigger project and i want to automate it a little bit.

As you can see I create my <MyButton> with both "isActive" and "type" props. But isActive holds what's inside this.state.settings while type is "settings". Instead of using two variables it would be great to pass only type of button to its component and component, depending on its type would check its parent's this.state.{type}. I used {type} because i would like to check it dynamically. Is that possible?

If so - how to do it?

My first attempt is to pass type from <MyButton> to <App> via toggler function. I named the variable "abc". I commented the way I wanted to do it because it doesn't work:

{abc}: !this.state.{abc}

Any idea to solve this problem would be more than appreciated. Kalreg.

It is somewhat unclear what you are trying to achieve here. If you want to wire the state dynamically based on type, as you wrote in code: {abc}: !this.state.{abc} each button would toggle itself, not the next button. In this case your syntax is a little incorrect, it will work if you write it like:

[abc]: !this.state[abc]

However as I said, in your example, this makes the settings button change the state for this.state.settings disabling itself instead of the next button.

Another note would be, that if it is not necessary for the MyButton component to know its own type for other reasons, it is unnecessary to pass it as a prop and than make the component pass it back as an argument ( this.props.toggle(this.props.type); ). You can simply define the toggle function in the parent as:

toggle={() => this.toggler("settings")}

without passing type as a prop.

So basically we want to have the settings and settings2 buttons, and when we click on them, they toggle the state of the next button by making it un-clickable (green).

So if that is our goal, then

  • we don't need an isActive prop for the settings button. (Because it's always going to be active no matter what)
  • We also don't need to have a toggle prop on the Next button. (Because clicking the next button isn't supposed to toggle anything)
  • Instead of having two variables in the state why not just have one and then use that to determine the isActive prop of the next button?

The component would look like this:

constructor() {
        super();
        this.state = {
            nextIsActive: false,
        };
    }

    toggler() {
        this.setState({
            nextIsActive: !this.state.nextIsActive
        }) 

        console.log(this.state);
    }

    render() {
        const {nextIsActive} = this.state

        return (
            <div className="kalreg">
                <MyButton name='settings' isActive={true} type="settings" toggle={this.toggler.bind(this)}/>
                <MyButton name='settings2' isActive={true} type="settings" toggle={this.toggler.bind(this)}/>
                <MyButton name='next' isActive={nextIsActive}/>
            </div>
        )
    }

That way you don't have to have 2 state properties that you have to dynamically update because it adds more complexity to your application.

You can see the finished product here: Codepen

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM