反应无状态子组件不会更新父组件中的状态更改
react stateless child components do not update on state change in parent component
我正在构建一个小型选项卡式应用程序,其中每个选项卡都呈现一个子组件。
我希望每个选项卡显示不同的内容,因此我在 render(){ .... }
之外创建了一个对象 contentTypes
以将每个选项卡映射到它对应的子组件。子组件通过 props 接收处理程序和状态。
class App extends Component {
state ={
contentType: "A",
title: "Overview",
searchContent: ""
}
tabHandler= (content,event)=>{
console.log("clicked");
this.setState({
title: event.target.name,
contentType: content
});
}
searchHandler = (event) => {
// this performs a search on a database and
//returns suggestions for the current input
this.setState({
searchContent: event.target.value
});
}
contentTypes = {
A: <A/>,
B: <B/>,
C: <C onchange={this.searchHandler.bind(this)} content={this.state.searchContent}/>
};
render() {
return (
<div className="row">
<ul>
<Tab click={this.tabHandler.bind(this)} id="A" name="A"/>
<Tab click={this.tabHandler.bind(this)} id="B" name="B"/>
<Tab click={this.tabHandler.bind(this)} id="C" name="C"/>
</ul>
<h1 id="title">{this.state.title}</h1>
{this.contentTypes[this.state.contentType]}
</div>
);
}
}
子组件是无状态的,定义有点像这样:
import React from 'react'
import Field from './form-builder/field';
const C = (props) => {
return(
// Field is another stateless component with formatted <input> tags
<Field type="text" name="search" content={props.content} onchange={props.onchange}/>
);
}
export default C;
字段定义如下:
import React from 'react';
const field = (props) => {
<li className="field">
<input type="text" onChange={props.onchange} value={props.content} />
<label htmlFor={props.name}>{props.value}</label>
</li>
}
export default field;
问题是,当我从 Field
内部调用处理程序来更新父组件(带有 render(){ .... }
的组件)中的状态时,子组件不会更新为新的状态。
关于如何解决这个问题有什么想法吗?
您将 contentTypes
定义为 class 属性。
它实际上与:
class App extends Component {
constructor() {
this.contentTypes = {
A: <A />,
B: <B />,
C: <C
onchange={this.searchHandler.bind(this)}
content={this.state.searchContent}/>
}
}
}
所以在构造函数中渲染的元素永远不会得到任何道具更新。
这是解决此问题的方法:
class App extends Component {
contentTypes = {
A: () => (<A/>),
B: () => (<B/>),
C: () => (
<C
onchange={this.searchHandler.bind(this)}
content={this.state.searchContent} />
)
}
// ...
render () {
const Content = this.contentTypes[this.state.contentType]
return (
<div>
{/* ... */}
<Content />
</div>
)
}
}
我正在构建一个小型选项卡式应用程序,其中每个选项卡都呈现一个子组件。
我希望每个选项卡显示不同的内容,因此我在 render(){ .... }
之外创建了一个对象 contentTypes
以将每个选项卡映射到它对应的子组件。子组件通过 props 接收处理程序和状态。
class App extends Component {
state ={
contentType: "A",
title: "Overview",
searchContent: ""
}
tabHandler= (content,event)=>{
console.log("clicked");
this.setState({
title: event.target.name,
contentType: content
});
}
searchHandler = (event) => {
// this performs a search on a database and
//returns suggestions for the current input
this.setState({
searchContent: event.target.value
});
}
contentTypes = {
A: <A/>,
B: <B/>,
C: <C onchange={this.searchHandler.bind(this)} content={this.state.searchContent}/>
};
render() {
return (
<div className="row">
<ul>
<Tab click={this.tabHandler.bind(this)} id="A" name="A"/>
<Tab click={this.tabHandler.bind(this)} id="B" name="B"/>
<Tab click={this.tabHandler.bind(this)} id="C" name="C"/>
</ul>
<h1 id="title">{this.state.title}</h1>
{this.contentTypes[this.state.contentType]}
</div>
);
}
}
子组件是无状态的,定义有点像这样:
import React from 'react'
import Field from './form-builder/field';
const C = (props) => {
return(
// Field is another stateless component with formatted <input> tags
<Field type="text" name="search" content={props.content} onchange={props.onchange}/>
);
}
export default C;
字段定义如下:
import React from 'react';
const field = (props) => {
<li className="field">
<input type="text" onChange={props.onchange} value={props.content} />
<label htmlFor={props.name}>{props.value}</label>
</li>
}
export default field;
问题是,当我从 Field
内部调用处理程序来更新父组件(带有 render(){ .... }
的组件)中的状态时,子组件不会更新为新的状态。
关于如何解决这个问题有什么想法吗?
您将 contentTypes
定义为 class 属性。
它实际上与:
class App extends Component {
constructor() {
this.contentTypes = {
A: <A />,
B: <B />,
C: <C
onchange={this.searchHandler.bind(this)}
content={this.state.searchContent}/>
}
}
}
所以在构造函数中渲染的元素永远不会得到任何道具更新。
这是解决此问题的方法:
class App extends Component {
contentTypes = {
A: () => (<A/>),
B: () => (<B/>),
C: () => (
<C
onchange={this.searchHandler.bind(this)}
content={this.state.searchContent} />
)
}
// ...
render () {
const Content = this.contentTypes[this.state.contentType]
return (
<div>
{/* ... */}
<Content />
</div>
)
}
}