首页 > 解决方案 > 使用 GetDerivedStateFromProps 初始化后将道具变为状态?

问题描述

我有以下超级简单的组件:

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,然后将显示在输入字段中。由于用户应该能够编辑此输入字段,因此我不能简单地将道具直接放入输入字段,而是使用状态。所以我从道具初始化组件状态。

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

ComponentWillReceiveProps在被弃用的 React 16.3 中,我将如何解决这样的问题?我试过调查GetDerivedStateFromProps,但我不完全了解如何使用它。

标签: javascriptreactjsreact-redux

解决方案


我不会尝试将不受控制的组件与受控组件同步,因为当组件扩展时逻辑会变得疯狂。

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

这是一个运行示例:

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);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
<div id="root"/>


推荐阅读