ReactJS - 如何从通过获取数据填充的props正确初始化状态?

Mas*_*gol 8 javascript reactjs

这是我的编辑组件:

class EditField extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: '' };
  }
  edit(e) {
    this.setState({ value: e.target.value });
    if (e.keyCode === 13) {
      this.props.onEdited(this.state.value);
    }
  }
  render() {
    return (
      <div>
        <input
          type="text"
          value={this.state.value}
          onChange={this.edit.bind(this)}
        />
      </div>
    )
  }
}
Run Code Online (Sandbox Code Playgroud)

我需要从像这样的道具填充状态:

function Container({ entity, onEdited }) {
  return (
    <div>
      <EditField onEdited={onEdited} value={entity.firstName} />
      <EditField onEdited={onEdited} value={entity.lastName} />
    </div>
  );
}
Run Code Online (Sandbox Code Playgroud)

Container组件GET onEditedentity道具终极版店. Container的父级将处理数据提取和onEdited(只有在用户命中时才会触发Enter)将dispatch请求服务器.

我的问题是如何value正确初始化道具?因为如果我使用:

  componentDidMount() {
    this.setState({
      value: this.props.value
    });
  }
Run Code Online (Sandbox Code Playgroud)

我得到了空状态,因为在componentDidMount 调用时没有完成提取数据.如果我使用:

  componentWillReceiveProps(nextProps) {
    this.setState({
      value: nextProps.value
    });
  }
Run Code Online (Sandbox Code Playgroud)

我收到了这个警告:

Warning: EditField is changing a controlled input of type text to be
unncontrolled. Input elements should not switch from controlled to
uncontrolled (or vice versa). Decide between using a controlled or
uncontrolled input element for the lifetime of the component.
Run Code Online (Sandbox Code Playgroud)

那么,如何正确地做到这一点?

And*_*ena 2

这就是我的建议:

  • 您可以使用from EditField从道具中getInitialState填充状态。但这是行不通的,因为只会被调用一次,所以后续的渲染不会更新状态。此外,这是一种反模式valuevaluegetInitialState
  • 您应该EditField控制该组件。始终将当前value作为 prop 传递,并完全停止处理状态。如果您想要一个库来帮助您将输入状态与 Redux链接起来,请查看Redux-Form
  • 您创建的事件onEdited(至少以您的方式)不能很好地处理受控输入,因此,您想要做的是拥有一个onChange始终使用新值触发的事件,因此 Redux 状态将始终发生变化。当用户按下 Enter 键(例如 )时,您可能onEnterPressed会触发另一个事件,因此您可以调用服务器并更新实体值。再次。Redux-Form 可以在这里提供帮助。
  • 显然entity.firstNameentity.lastName只能包含用户已确认的值(按 Enter 键),而不是临时值。如果是这种情况,请尝试将表单的状态与实体的状态分开。表单的状态可以通过 Redux-Form 来控制。当用户按下回车键时,您可以触发一个实际调用服务器并更新实体状态的操作。您甚至可以设置“正在加载”状态,以便在调用服务器时禁用表单。