Javascript 反应从表中删除特定行
我有一个组件,它是一个表。 此表的每一行也是组件Javascript 反应从表中删除特定行,javascript,arrays,reactjs,Javascript,Arrays,Reactjs,我有一个组件,它是一个表。 此表的每一行也是组件 class FormulaBuilder extends Component { constructor(props) { super(props); this.state = { rows: [{}] } } handleAddRow = () => { const item =
class FormulaBuilder extends Component {
constructor(props) {
super(props);
this.state = {
rows: [{}]
}
}
handleAddRow = () => {
const item = {};
this.setState({
rows: [...this.state.rows, item]
});
};
handleRemoveSpecificRow = (idx) => {
const rows = [...this.state.rows]
rows.splice(idx, 1)
this.setState({ rows })
}
render() {
return (
{
this.state.rows.map((item, idx) => {
return (
<React.Fragment key={idx}>
<ConcoctionRow
removeSpecificRow={(idx) =>this.handleRemoveSpecificRow(idx)}
id={idx} />
</React.Fragment>);
})
});
}
}
属性通过了数组的索引。但只有最后一行始终被删除,不具体
我的坏朋友在哪里?另外,我是JS新手。
有几件事,您希望避免使用.splice()更新组件中的数组。通常情况下,这实际上会改变您的原始状态,而不是创建新状态。直接违反反应概念
同样,让我们在控制台上尝试一些东西:const arr = [1, 2, 3] <-- this is your state
const newArr = arr <-- you created a reference of your state. This does not actually create a new copy.
事实并非如此,您的新变量不是显式创建新副本,而是指向它所派生的原始对象的同一引用。如果我这样做:
myCat.age = 2 <-- Now myCat has a new property of age.
myCat <-- {id: 2, name: "bunny", age: 2}
有几件事需要避免使用.splice()更新组件中的数组。通常情况下,这实际上会改变您的原始状态,而不是创建新状态。直接违反反应概念 同样,让我们在控制台上尝试一些东西:
const arr = [1, 2, 3] <-- this is your state
const newArr = arr <-- you created a reference of your state. This does not actually create a new copy.
事实并非如此,您的新变量不是显式创建新副本,而是指向它所派生的原始对象的同一引用。如果我这样做:
myCat.age = 2 <-- Now myCat has a new property of age.
myCat <-- {id: 2, name: "bunny", age: 2}
我展示了我将用于此案例的模式。我建议对项目使用
id
而不是数组索引。
filter
array函数是不可变的(它创建一个新数组,而不是变异前一个数组),所以可以在设置状态下使用。setState
的函数形式也是一个好东西
const行=({onClick,children,id})=>(
{children}onClick(id)}>Delete
)
类应用程序扩展了React.Component{
状态={
名单:[
{id:1,标签:'foo'},
{id:2,标签:'bar'}
]
}
handleDelete=id=>{
this.setState(prevState=>({
列表:prevState.list.filter(行=>(
row.id!==id
))
}))
}
render(){
const{list}=this.state;
返回(
{list.map({id,label})=>(
{label}
))}
)
}
}
ReactDOM.render(,document.getElementById('root'))代码>
我展示了我将用于此案例的模式。我建议对项目使用id
而不是数组索引。
filter
array函数是不可变的(它创建一个新数组,而不是变异前一个数组),所以可以在设置状态下使用。setState
的函数形式也是一个好东西
const行=({onClick,children,id})=>(
{children}onClick(id)}>Delete
)
类应用程序扩展了React.Component{
状态={
名单:[
{id:1,标签:'foo'},
{id:2,标签:'bar'}
]
}
handleDelete=id=>{
this.setState(prevState=>({
列表:prevState.list.filter(行=>(
row.id!==id
))
}))
}
render(){
const{list}=this.state;
返回(
{list.map({id,label})=>(
{label}
))}
)
}
}
ReactDOM.render(,document.getElementById('root'))代码>
removeSpecificRow是用行的id调用的,但是在HandlerRemoveSpecificRow中调用rows.splice时,您假设它是索引。你确定索引和id完全匹配吗?是的,只是一个值的名称不同。不要使用idx
作为React.Fragment
的键。简而言之,你的项应该有一个唯一的id,它不会随时间而改变,所以你可以将该值传递给remove函数,类似这样的removespecicrow={()=>this.handleRemoveSpecificRow(item.uid)}
removeSpecificRow是用行的id调用的,但是在调用handleRemoveSpecificRow.splice中的rows.splice时,假设它是索引。你确定索引和id完全匹配吗?是的,只是一个值的名称不同。不要使用idx
作为React.Fragment
的键。简而言之,你的项应该有一个唯一的id,它不会随时间而改变,所以你可以将该值传递给remove函数,类似这样的removespecicrow={()=>this.handleRemoveSpecificRow(item.uid)}
关于避免拼接的公平点,但在OP中使用它很好,因为它们避免使用排列创建引用:const rows=[…this.state.rows]
创建一个新的rows
数组,其中包含state.rows
@pawel的值,你知道吗,你完全正确。在我的沙箱中运行OP的代码,实际上我看不出他提到的问题。关于避免拼接
,这一点很有道理,但在OP中使用它很好,因为它们避免使用spread创建引用:const rows=[…this.state.rows]
创建一个新的行
数组,其中包含来自状态的值。行
@pawel,你知道吗,你完全正确。在我的沙箱中运行OP的代码,我实际上没有看到他提到的问题。
let cat = {id: 1, name: "bunny"}
let myCat = cat
myCat.age = 2 <-- Now myCat has a new property of age.
myCat <-- {id: 2, name: "bunny", age: 2}
cat <-- {id: 2, name: "bunny", age: 2}
import React from "react";
import ConcoctionRow from "./ConcoctionRow";
class FormulaBuilder extends React.Component {
constructor(props) {
super(props);
this.state = {
rows: [{}, {}, {}]
};
}
handleAddRow = () => {
const item = {};
this.setState({
rows: [...this.state.rows, item]
});
};
handleRemoveSpecificRow = idx => {
const { rows } = this.state;
const updatedRows = rows.filter((row, index) => {
return index !== idx;
});
this.setState({
rows: updatedRows
});
};
render() {
return (
<div>
{this.state.rows.map((item, idx) => {
return (
<React.Fragment key={idx}>
<ConcoctionRow
removeSpecificRow={this.handleRemoveSpecificRow}
id={idx}
/>
</React.Fragment>
);
})}
</div>
);
}
}
export default FormulaBuilder;