简体   繁体   中英

How can I use a prop to define the initial state of a modal dialog when it opens in ReactJS?

I have been reading a lot that in React, tying a prop to a state is an anti-pattern, and I feel this way too. But I want to create a modal dialog which when opened, it will use a prop to define the inertial state of the dialog. So in this prop, I would pass in a list of People objects, and my dialog would create an editable form, with a row for each person.

var peopleList = [
{name: "person1", address: "address1"},
{name: "person2", address: "address2"}
];

<Dialog people={peopleList} />

It would need to store the prop into it's state. But then this dialog would have a button to create more rows in the form to enter data about more people. Pressing this button would cause the state in the dialog to change, but the data the dialog's prop was based on would not change. Since the dialog is modal, is this really a bad thing?

According to the documentation:

However, it's not an anti-pattern if you make it clear that synchronization's not the goal here

And by "here" they're referring to the following code:

var Counter = React.createClass({
  getInitialState: function() {
    // naming it initialX clearly indicates that the only purpose
    // of the passed down prop is to initialize something internally
    return {count: this.props.initialCount};
  },

  handleClick: function() {
    this.setState({count: this.state.count + 1});
  },

  render: function() {
    return <div onClick={this.handleClick}>{this.state.count}</div>;
  }
});

React.render(<Counter initialCount={7}/>, mountNode);

As you can see here, instead of naming the expected property as count -- which, semantically, means a property that will remain static all along--you call it initialCount to indicate that the property will eventually change over time, and that is not an anti-pattern.

So, in your code, instead of naming the expected people property as people , give it the name of initialPeopleList .

As a side note, I notice that you are passing in a non-copied reference of peopleList . Just be sure that your component does not modify the content of peopleList directly, but instead returns a new copy for each modification.

// THIS IS BAD! REALLY BAD!

push(person) {

  // This is modifying the list directly!
  // Don't do this!
  this.state.people.push(person);

  this.setState({
    people: this.state.people
  });

}

// -------------------------

// THIS IS MUCH BETTER!

push(person) {
  this.setState({
    // `concat` returns a new copy, leaving the original intact!
    people: this.state.people.concat([person]);
  })
}

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