避免在 React Flux 应用程序中重新呈现受控输入

Avoiding re-renders for controlled inputs in a React Flux application

我的应用程序中有一个经典的 Flux 模式,使用 fluxible。输入的 value 与我的组件的 prop 相关联,它的 onChange 调用一个动作,该动作依次更新一个存储,而该存储又将一个 prop 传递到我的组件中:

class MyComponent extends React.Component {
  handleChange(e) {
    this.context.executeAction(persist, { value: e.target.value });
  }

  render() {
    return <input value={this.props.value} onChange={this.handleChange.bind(this)}/>;
  }
}

我遇到的问题是,当商店发出更改并且新值传递到我的组件时,这会导致它重新呈现,并且输入光标位置丢失(移动到末尾).

我知道我可以为我的组件创建一个自定义的 shouldComponentUpdate 方法,但是这样做有点棘手而且绝对乏味,因为我认为这是一个非常频繁出现的模式。

是否有一个完善的模式来避免重新渲染受控输入?

我发现 ReactLink 的描述给出了处理这类事情的一个很好的模式。这是我想出的:

class MyComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { value: props.value };
    this.handleChange = this.handleChange.bind(this);
  }

  componentWillReceiveProps(newProps) {
    // If in some cases you want to handle a new value prop, update state here
  }

  handleChange({ target: { value } }) {
    this.setState({ value });
    this.context.executeAction(persist, { value });
  }

  render() {
    return <input value={this.state.value} onChange={this.handleChange}/>;
  }
}

基本上,忽略那些说"if you set state based on a prop you're doing it wrong"的人,根据道具设置你的初始状态。此状态是您的输入现在用于其值的状态。然后,假设新的 value 道具确实进来了,它们不会影响你的 render 输出。如果您确实希望他们这样做,您可以向 componentWillReceiveProps 添加逻辑。例如,在我的例子中,我确实想更新输入,但前提是它没有被聚焦:

componentWillReceiveProps({ value }) {
  if (!this.state.isFocused) {
    this.setState({ value });
  }
}