尽管在父级上调用了 setState,但 React 仍未渲染某些组件
React not rendering some components despite calling setState on parent
我正在尝试编写一个计算器类型的应用程序(即我给它一个输入列表,它对它们执行计算并显示结果),但是对于某些输入它不会更新当输入改变时输出。我的代码的相关部分:
class Results extends React.Component
{
constructor (props)
{
super (props);
}
render ()
{
let entries = calculate (this.props);
return <div className="results">
{entries.map(e => <ResultRow key={e.code} code={e.code} name={e.name} />)}
</div>;
}
}
class CircuitRow extends React.Component
{
constructor (props)
{
super (props);
this.state = props.circuit;
this.nameChange = this._nameChange.bind(this);
}
_nameChange (evt)
{
this.state.name = evt.target.value;
this.setState (this.state);
if (this.props.notifyChange) this.props.notifyChange (this.props.circuit);
}
render ()
{
return <tr>
<td><input className="label" value={this.state.name} onChange={this.nameChange} /></td>
(more fields deleted as not necessary to demonstrate issue)
</tr>;
}
}
class Form extends React.Component
{
constructor(props) {
super(props);
this.state = {
circuits: [
{ id: 1, name: "circuit 1", ... other fields ... },
{ id: 2, name: "circuit 2", ... },
{ id: 3, name: "circuit 3", ... } ],
colours: "RBWK",
nextRowId: 4
};
this.notifyCircuitChange = this._notifyCircuitChange.bind(this);
}
render ()
{
return <div>
<form className='optionsForm'>
(working part of form for changing colours removed)
<table><tbody>
<tr><th>Circuit Name</th><th>Count</th></tr>
{this.state.circuits.map ((circuit, i) =>
<CircuitRow key={circuit.id} index={i} circuit={circuit} notifyChange={this.notifyCircuitChange} />)}
</tbody></table>
</form>
<Results colours={this.state.colours} circuits={this.state.circuits} />
</div>;
}
_notifyCircuitChange (circuit) { this.setState(this.state); }
}
ReactDOM.render (<Form/>, document.getElementById('main'));
我没有显示 做 工作的部分表单,包括一组更改 Form.state.colours 字符串内容的复选框 -- 结果确实如此当我更改这些时成功更新,但是当我更改电路行之一的 'name' 字段时,新名称未显示在结果中 table,但旧名称保留在那里。
知道为什么没有更新吗?
在您的代码中,您将 nameField 的值存储为 CircuitRow 组件的状态,每次发生更改时,您都会在两个地方更新相同的内容:CircuitRow 的状态和父级的状态形式。相反,我建议您将 nameField 的值作为道具传递给 CircuitRow 组件并显示,每次有更改时,您应该触发一个回调函数,该函数在父状态中发生相同的更改。
您的电路数组最初看起来像这样:
[
{ id: 1, name: "circuit 1", value: "", ... other fields ... },
{ id: 2, name: "circuit 2", value: "", ... },
{ id: 3, name: "circuit 3", value: "", ... } ]
将值作为道具传递给每个 CircuitRow 组件,并在渲染中显示它。
更改时,从 CircuitRow 触发 notifyChange,更新 Form 组件中的值。
我认为问题出在这个函数中,你从 CircuitRow
组件传递道具值,就像你从 parent 收到的任何东西一样,你从 [=24= 传递相同的值],试试这个:
_nameChange (evt)
{
let circuit = this.state.circuit;
circuit.name = evt.target.value;
this.setState({circuit});
if (this.props.notifyChange)
this.props.notifyChange(circuit);
}
还有一件事,您需要将 id 传回 parent Form
以更改此函数中 parent 中指定的元素,因为在 Form
组件中你有一个数组 od circuits
并且你必须只更新特定的元素。像这样:
_nameChange (evt)
{
let circuit = this.state.circuit;
circuit.name = evt.target.value;
this.setState({circuit});
if (this.props.notifyChange)
this.props.notifyChange(circuit, this.props.key);
}
并且在 _notifyCircuitChange
方法中:
_notifyCircuitChange (circuit, id)
{
let circuits = this.state.circuits;
for(let i in circuits){
if(circuits[i].id == id){
circuits[i] = circuit;
break;
}
}
this.setState({circuits});
}
我正在尝试编写一个计算器类型的应用程序(即我给它一个输入列表,它对它们执行计算并显示结果),但是对于某些输入它不会更新当输入改变时输出。我的代码的相关部分:
class Results extends React.Component
{
constructor (props)
{
super (props);
}
render ()
{
let entries = calculate (this.props);
return <div className="results">
{entries.map(e => <ResultRow key={e.code} code={e.code} name={e.name} />)}
</div>;
}
}
class CircuitRow extends React.Component
{
constructor (props)
{
super (props);
this.state = props.circuit;
this.nameChange = this._nameChange.bind(this);
}
_nameChange (evt)
{
this.state.name = evt.target.value;
this.setState (this.state);
if (this.props.notifyChange) this.props.notifyChange (this.props.circuit);
}
render ()
{
return <tr>
<td><input className="label" value={this.state.name} onChange={this.nameChange} /></td>
(more fields deleted as not necessary to demonstrate issue)
</tr>;
}
}
class Form extends React.Component
{
constructor(props) {
super(props);
this.state = {
circuits: [
{ id: 1, name: "circuit 1", ... other fields ... },
{ id: 2, name: "circuit 2", ... },
{ id: 3, name: "circuit 3", ... } ],
colours: "RBWK",
nextRowId: 4
};
this.notifyCircuitChange = this._notifyCircuitChange.bind(this);
}
render ()
{
return <div>
<form className='optionsForm'>
(working part of form for changing colours removed)
<table><tbody>
<tr><th>Circuit Name</th><th>Count</th></tr>
{this.state.circuits.map ((circuit, i) =>
<CircuitRow key={circuit.id} index={i} circuit={circuit} notifyChange={this.notifyCircuitChange} />)}
</tbody></table>
</form>
<Results colours={this.state.colours} circuits={this.state.circuits} />
</div>;
}
_notifyCircuitChange (circuit) { this.setState(this.state); }
}
ReactDOM.render (<Form/>, document.getElementById('main'));
我没有显示 做 工作的部分表单,包括一组更改 Form.state.colours 字符串内容的复选框 -- 结果确实如此当我更改这些时成功更新,但是当我更改电路行之一的 'name' 字段时,新名称未显示在结果中 table,但旧名称保留在那里。
知道为什么没有更新吗?
在您的代码中,您将 nameField 的值存储为 CircuitRow 组件的状态,每次发生更改时,您都会在两个地方更新相同的内容:CircuitRow 的状态和父级的状态形式。相反,我建议您将 nameField 的值作为道具传递给 CircuitRow 组件并显示,每次有更改时,您应该触发一个回调函数,该函数在父状态中发生相同的更改。
您的电路数组最初看起来像这样:
[
{ id: 1, name: "circuit 1", value: "", ... other fields ... },
{ id: 2, name: "circuit 2", value: "", ... },
{ id: 3, name: "circuit 3", value: "", ... } ]
将值作为道具传递给每个 CircuitRow 组件,并在渲染中显示它。 更改时,从 CircuitRow 触发 notifyChange,更新 Form 组件中的值。
我认为问题出在这个函数中,你从 CircuitRow
组件传递道具值,就像你从 parent 收到的任何东西一样,你从 [=24= 传递相同的值],试试这个:
_nameChange (evt)
{
let circuit = this.state.circuit;
circuit.name = evt.target.value;
this.setState({circuit});
if (this.props.notifyChange)
this.props.notifyChange(circuit);
}
还有一件事,您需要将 id 传回 parent Form
以更改此函数中 parent 中指定的元素,因为在 Form
组件中你有一个数组 od circuits
并且你必须只更新特定的元素。像这样:
_nameChange (evt)
{
let circuit = this.state.circuit;
circuit.name = evt.target.value;
this.setState({circuit});
if (this.props.notifyChange)
this.props.notifyChange(circuit, this.props.key);
}
并且在 _notifyCircuitChange
方法中:
_notifyCircuitChange (circuit, id)
{
let circuits = this.state.circuits;
for(let i in circuits){
if(circuits[i].id == id){
circuits[i] = circuit;
break;
}
}
this.setState({circuits});
}