一旦用户更新输入的收件箱,显示的eName就会更改。它不更新阵列。是什么原因造成的?
错误消息:
TypeError:无法设置未定义App.inputChangeHandler的属性'eName'
代码:
class App extends Component {
state= {
product:[
{eName:"Anu", eNo:"1200", eSalary:"1000"},
{eName:"Jack", eNo: "1201", eSalary:"1200"},
{eName:"Ben", eNo: "1202", eSalary:"1300"}
],
showFlag:true,
}
inputChangeHandler(event,index){
const mProducts = this.state.product;
mProducts[index].eName = event.target.value;
console.log(event.target.value);
this.setState({
product:mProducts
})
}
deleteHandler(index){
console.log("delete clicked" + index);
const mProducts = this.state.product;
mProducts.splice(index,1);
this.setState({
product:mProducts
})
}
showHideHandler=()=>{
this.setState({
showFlag:!this.state.showFlag
})
console.log(this.state.showFlag);
}
render(){
let dp = null;
if (this.state.showFlag === true){
dp =(
<div className ="App">
{this.state.product.map((product,index) => {
return (
<Product
eName={product.eName}
eNo={product.eNo}
eSalary={product.eSalary}
key ={index}
click ={this.deleteHandler.bind(this.index)}
inputChange={this.inputChangeHandler.bind(this)}
/>)
})}
</div>
)
}
return(
<div className ="App">
{dp}
<hr/>
<button onClick={()=>this.showHideHandler()}>show hide</button>
<h2>{this.state.eName} </h2>
</div>
);
}
}
export default App;
一旦用户更新输入的收件箱,显示的eName就会更改。它不更新阵列。
答案 0 :(得分:0)
问题是因为inputChangeHandler
函数未收到正确的索引。请进行以下更改:
将inputChangeHandler
定义为箭头函数:
inputChangeHandler = (event,index) => {
const mProducts = this.state.product;
mProducts[index].eName = event.target.value;
console.log(event.target.value);
this.setState({
product:mProducts
})
}
在render
函数内部,在调用inputChangeHandler
时,同时传递事件和索引
render(){
let dp = null;
if (this.state.showFlag === true){
dp =(
<div className ="App">
{this.state.product.map((product,index) => {
return (
<Product
eName={product.eName}
eNo={product.eNo}
eSalary={product.eSalary}
key ={index}
click ={this.deleteHandler.bind(this.index)}
inputChange={(e) => this.inputChangeHandler(e, index)}
/>)
})}
</div>
)
}
return(
<div className ="App">
{dp}
<hr/>
<button onClick={()=>this.showHideHandler()}>show hide</button>
<h2>{this.state.eName} </h2>
</div>
);
}
答案 1 :(得分:0)
您正在更改状态,并在所有处理程序中使用已更改状态执行setState。因为React看不到状态变化,所以它不会重新呈现(尝试将console.log放入render中,您会看到它不会显示在控制台中)。
以下是您在不更改状态的情况下将其设置为状态的方法:
inputChangeHandler(event, index) {
this.setState({
product: this.state.product.map((product, i) =>
i === index
? { ...product, eName: event.target.value }
: product
),
});
}
我建议最好为变量命名,如果您有产品列表,则最好将其命名为products
(复数)而不是product
(单数)。
如果您让React渲染元素列表并且可以删除或排序元素,那么您不应该将index用作键,产品不具有可以使用的唯一ID,否则请问为什么?
以下是如何将事件处理程序发送到产品的示例:
class App extends React.Component {
state = {
products: [
{ id: 1, eName: 'Anu', eNo: '1200', eSalary: '1000' },
{
id: 2,
eName: 'Jack',
eNo: '1201',
eSalary: '1200',
},
{ id: 3, eName: 'Ben', eNo: '1202', eSalary: '1300' },
],
showFlag: true,
};
//arrow function will auto bind
inputChangeHandler = (eName, id) => {
this.setState({
products: this.state.products.map(p =>
p.id === id ? { ...p, eName } : p
),
});
};
//arrow function will auto bind
deleteHandler = id => {
this.setState({
products: this.state.products.filter(
p => p.id !== id
),
});
};
showHideHandler = () => {
this.setState({
showFlag: !this.state.showFlag,
});
};
render() {
let dp = null;
if (this.state.showFlag === true) {
dp = (
<div className="App">
{this.state.products.map((product, index) => {
return (
<Product
key={product.id}
{...product}
remove={this.deleteHandler}
inputChange={this.inputChangeHandler}
/>
);
})}
</div>
);
}
return (
<div className="App">
{dp}
<hr />
<button onClick={() => this.showHideHandler()}>
show hide
</button>
<h2>{this.state.eName} </h2>
</div>
);
}
}
//make this a pure component with React.memo
const Product = React.memo(function Product({
remove,
id,
eName,
inputChange,
}) {
console.log('rendering:', id);
return (
<div>
<button onClick={() => remove(id)}>delete</button>
<input
type="text"
value={eName}
onChange={e => inputChange(e.target.value, id)}
></input>
</div>
);
});
//render app
ReactDOM.render(
<App />,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<div id="root"></div>
答案 2 :(得分:0)
您还应该将index
传递给Product
组件,
{this.state.product.map((product,index) => {
return (
<Product
eName={product.eName}
eNo={product.eNo}
eSalary={product.eSalary}
key = {index}
ind = {index} //pass index here
click ={this.deleteHandler.bind(this.index)}
inputChange={this.inputChangeHandler.bind(this)}
/>
)
})}
您的Product
组件应为(根据您的评论),
import React from 'react'
import './employee.css'
function Employee(props) {
return (
<div className ="prod">
<h1> Name:{props.eName}</h1>
<h2> Emp-No:{props.eNo}</h2>
<h3> Salary:{props.eSalary}</h3>
<button onClick ={props.click}> delete</button>
<input onChange={(e) => props.inputChange(e,props.ind)} value={props.eName} type="text"/> //pass `event` & `index` to `inputChange` function here
</div>
)
}
export default Employee;