我很困。我正在构建一个反应式闪存卡应用程序,并且在状态是对象数组时询问了一些有关设置状态的问题。我一直在研究不同的解决方案,而且看起来非常接近,但是似乎无法正常运行此代码。这是我的组件:
import React, { Component } from 'react'
export class TermForm extends Component {
state = {
allTerms: [
{
term: '',
def: ''
},
{
term: '',
def: ''
},
{
term: '',
def: ''
},
{
term: '',
def: ''
},
{
term: '',
def: ''
},
{
term: '',
def: ''
},
{
term: '',
def: ''
},
{
term: '',
def: ''
},
{
term: '',
def: ''
},
{
term: '',
def: ''
}
]
}
onChangeTerm = (event, index) => {
event.preventDefault();
this.setState({
allTerms : [
...this.state.allTerms.splice(0,index) ,
{
...this.state.allTerms[index],
term: event.target.value
},
...this.state.allTerms.splice(index+1) ,
]
})
}
onChangeDef = (e, index) => {
e.preventDefault();
this.setState({
allTerms : [
...this.state.allTerms.splice(0,index) ,
{
...this.state.allTerms[index],
def: e.target.value
},
...this.state.allTerms.splice(index+1)
]
})
}
render() {
return (
this.props.numberOfTerms.map((index) => (
<div key={index}>
<input type="text" placeholder="TERM" value={this.state.allTerms.term} onChange={(event) => this.onChangeTerm(event, index)}></input>
<input type="text" placeholder="DEFINITION" value={this.state.allTerms.def} onChange={(e) => this.onChangeDef(e, index)}></input>
</div>
))
)
}
}
export default TermForm
对于上下文,我的render方法中的return语句返回动态表单。基本上,根据用户要添加的术语数,呈现的表单可以有1到10行(每行包括一个用户想要添加的术语的输入字段,以及另一个定义的输入字段)的任意位置。对于术语和定义,我有单独的onChange事件。当我为第一个术语设置状态时(因此要通过onChangeTerm和onChangeDef函数进行设置),状态设置就很好了。但是,对于尝试在第一个卡片之后创建的任何数量的卡片,状态都会一团糟。通过查看chrome的react工具中的状态,我可以看到尝试创建第二张卡(以及第一张卡之后的任意数量的卡)后,该术语已设置完毕,但是当我输入定义时,它将清除该术语值。老实说,我很困惑。我以为问题出在我的onChange函数中的一个或两个中,但我似乎无法弄清楚问题出在哪里。任何帮助都将不胜感激。
答案 0 :(得分:2)
我建议将数组存储在父组件中,并使用TermForm
组件分别显示每个term + def。然后,当您更新一项/定义时,它会设置新状态并将信息传播到父项:https://codesandbox.io/s/pensive-morning-95cmx
我还渲染了应用程序状态以显示其正常工作;)还可以改善allTerms
数组的创建。例如用循环填充它
// App.js
import React, { Component } from "react";
import "./styles.css";
import { TermForm } from "./TermForm";
export default class App extends Component {
state = {
allTerms: [
{
term: "",
def: ""
},
{
term: "",
def: ""
},
{
term: "",
def: ""
},
{
term: "",
def: ""
},
{
term: "",
def: ""
}
]
};
updateTermDef = (term, def, idx) => {
const newTerms = [...this.state.allTerms];
newTerms[idx] = {
term,
def
};
this.setState({ allTerms: newTerms });
};
render() {
return (
<div className="App">
{this.state.allTerms.map((termDef, idx) => (
<TermForm
term={termDef.term}
def={termDef.def}
idx={idx}
updateTermDef={(term, def) => this.updateTermDef(term, def, idx)}
/>
))}
<h1>App state: </h1>
{this.state.allTerms.map(termDef => (
<>
<span>
{termDef.term} : {termDef.def}
</span>
<br />
</>
))}
</div>
);
}
}
//TermForm.js
import React, { Component } from "react";
export class TermForm extends Component {
state = {
term: this.props.term,
def: this.props.def
};
render() {
return (
<div key={this.props.idx}>
<input
type="text"
placeholder="TERM"
value={this.state.term}
onChange={event =>
this.setState(
{ term: event.currentTarget.value },
this.props.updateTermDef(this.state.term, this.state.def)
)
}
/>
<input
type="text"
placeholder="DEFINITION"
value={this.state.def}
onChange={event =>
this.setState(
{ def: event.currentTarget.value },
this.props.updateTermDef(this.state.term, this.state.def)
)
}
/>
</div>
);
}
}