避免在 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 });
}
}
我的应用程序中有一个经典的 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 });
}
}