使用GetDerivedStateFromProps初始化后将道具变成状态吗?

时间:2018-10-06 13:36:36

标签: javascript reactjs react-redux

我有以下超简单组件:

export default class Editor extends Component {
  constructor(props) {
    super(props);

    this.state = { field: "Some Initial Text" };

    this.handleChangeField = this.handleChangeField.bind(this);
  }

  handleChangeField(e) {
    this.setState({field: e.target.value});
  }

  render() {
    return (
        <div>
          <input type="text" name="word" value={this.state.field} onChange={this.handleChangeField} />
          {this.state.field}
        </div>
    );
  }
}

它只有一个字段。用户可以编辑该字段。根据用户在同级组件中单击的内容,上述组件将收到一个名为fieldValue的道具,然后该道具将在输入字段中显示。由于用户应该能够编辑此输入字段,因此我不能简单地将prop直接放入输入字段中,而要使用状态。因此,我从道具初始化了组件状态。

但是,即使在组件初始化后,此道具也可能会更改。也就是说,它不仅是一个初始值,而且在运行时可能会更改,具体取决于用户在同级组件中单击的内容。

在不赞成使用ComponentWillReceiveProps的情况下,如何在React 16.3中解决类似问题?我曾尝试研究GetDerivedStateFromProps,但我不完全了解如何使用它。

2 个答案:

答案 0 :(得分:1)

我不会尝试同步uncontrolled component with controlled component,因为当组件扩展时,逻辑可能会变得疯狂。

话虽如此,如果您真的想跟踪道具更改并相应地更新状态,则可以使用componentDidUpdate,但请确保在更新状态之前已获得一些有效条件。

这是一个正在运行的示例:

zip -r -9 /tmp/export.zip lib64/python3.6/site-packages/* lib64/python3.6/site-packages/.*
zip -r -9 /tmp/export.zip lib/python3.6/site-packages/* lib/python3.6/site-packages/.*
zip -r -9 /tmp/export.zip main.py   
class Editor extends React.Component {

  state = { field: this.props.defaultValue };

  componentDidUpdate(prevProps) {
    const { defaultValue } = this.props;
    if (prevProps.defaultValue !== defaultValue) {
      this.setState({ field: defaultValue });
    }
  }

  handleChangeField = (e) => {
    this.setState({ field: e.target.value });
  }

  render() {
    return (
      <div>
        <input type="text" name="word" value={this.state.field} onChange={this.handleChangeField} />
        {this.props.defaultValue}
      </div>
    );
  }
}

class App extends React.Component {
  state = { value: 'A default value' }

  handleChange = ({ target }) => this.setState({ value: target.value })

  render() {
    const { value } = this.state;
    return (
      <div>
        <h3>App </h3>
        <input type="text" value={value} onChange={this.handleChange} />
        <hr />
        <h3>Editor</h3>
        <Editor defaultValue={value} />
      </div>
    );
  }
}

const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

答案 1 :(得分:-1)

这非常简单,这是一个应该可以工作的原型:

export default class Editor extends Component {
  static getDerivedStateFromProps(props, state) {
    // You need to return object that will be used to fill the state, not manipulate the state itself
    return {
      field: state.field
    }
  }

  constructor(props) {
    super(props);

    this.handleChangeField = this.handleChangeField.bind(this);
  }

  handleChangeField(e) {
    this.setState({field: e.target.value});
  }

  render() {
    return (
        <div>
          <input type="text" name="word" value={this.state.field} onChange={this.handleChangeField} />
          {this.state.field}
        </div>
    );
  }
}