更改值后反应组件未更新
Posted
技术标签:
【中文标题】更改值后反应组件未更新【英文标题】:React Component Not Updating After Changing A Value 【发布时间】:2017-09-15 13:03:30 【问题描述】:在 ReactJS 中,我正在编写一个无状态组件; 因为我已经阅读了避免不必要的状态是最佳实践。
该组件表示一个输入字段,当输入框包含一个值时执行一个函数。
export const InputField = (props) =>
const InputFieldContentsChanged = (event) =>
props.onChange(event.target.value);
;
return (
<div data-component="input-field"
className=(props.value !== "" ? "value": "")>
<input type=props.type value=props.value onChange=InputFieldContentsChanged />
<span className="bar"></span>
<label>props.label</label>
</div>
);
;
InputField.PropTypes =
type: PropTypes.oneOf([ "text", "password" ]).isRequired,
label: PropTypes.string.isRequired,
value: PropTypes.string,
onChange: PropTypes.func.isRequired
现在, 我创建了另一个组件,它只是用于测试上述组件的示例。 如下所示:
export const SampleComponent = (props) =>
let componentUsername = "";
const onUsernameChanged = (username) =>
componentUsername = username;
;
return (
<InputField type="text" label="Username" value=componentUsername onChange=onUsernameChanged />
);
;
所以,我将value
绑定到组件中的自定义变量,当输入字段的内容发生更改时,该变量也会更改。
为什么输入框组件没有用新的用户名更新自己?
亲切的问候,
【问题讨论】:
你能搞定一个小提琴并运行吗? 无状态组件是无状态的。它们应该被实现为纯函数。返回值应仅取决于参数(道具)。由于没有任何东西改变道具 - 不会发生重新渲染。但是您的组件实际上并不是无状态的,它们确实具有可变的内部状态(输入值)。因此,您需要同时实现这两者或容器一个作为有状态组件。 【参考方案1】:功能组件的想法是不对状态或道具进行任何更改。
由于没有重新渲染组件的触发器,因此您不会看到任何变化。
将此React.Function
更改为React.Component
。
const InputField = (props) =>
const InputFieldContentsChanged = (event) =>
console.log(event.target.value);
props.onChange(event.target.value);
;
return (
<div data-component="input-field"
className=(props.value !== "" ? "value": "")>
<input type=props.type value=props.value onChange=InputFieldContentsChanged />
<span className="bar"></span>
<label>props.label</label>
</div>
);
;
class SampleComponent extends React.Component
constructor()
super();
this.state = componentUsername : "";
onUsernameChanged = (username) =>
console.log(username);
this.setState(componentUsername: username);
render()
return (
<InputField type="text" label="Username" value=this.state.componentUsername onChange=this.onUsernameChanged />
);
;
ReactDOM.render(<SampleComponent/>, document.getElementById('app'));
<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="app"></div>
【讨论】:
【参考方案2】:我正在编写一个无状态的 React 组件,因为最好的做法是在不需要时避免状态。
在您的代码中,您尝试使用自己的“状态”,它只是一个变量 (componentUsername
)。但由于它不是 React 状态,因此组件不会在变量更改时重新渲染。 React 根本不知道变化。
因此,要么使用通常的setState
而不是重新分配您自己的“状态”变量,或者将逻辑放在父组件中并通过道具将componentUsername
传递给SampleComponent
:
const SampleComponent = props => (
<input type="text" onChange=props.onChange value=props.value />
);
class ParentComponent extends React.Component
constructor()
super();
this.state = value: '' ;
this.handleInputChange = this.handleInputChange.bind(this);
handleInputChange(e)
console.log(e.target.value);
this.setState( value: e.target.value );
render()
return (
<SampleComponent
value=this.state.value
onChange=this.handleInputChange
/>
);
ReactDOM.render(<ParentComponent />, document.getElementById('root'));
<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"></div>
【讨论】:
谢谢。如果我没听错的话,“top-root”组件应该有“state”才能触发重新渲染,对吗? 另一件事,如果我将 componentUsername 作为属性分配给 InputField,那么由于组件无法更新它自己的 props,我该如何触发重新渲染? 是的,没错!当然,像 Redux 或 Mobx 这样的状态容器也有例外。 因为父组件更新了SampleComponent
的props。 componentUsername
在这种情况下应该是父状态的一部分。
好的,这就很清楚了。你能给我以下建议吗?我应该在父组件中维护状态,还是应该在 InputField 组件本身中使用内部状态?以上是关于更改值后反应组件未更新的主要内容,如果未能解决你的问题,请参考以下文章