I have a table, rendered from this data.
{
key: 1,
model: "11111111",
sn: "TERR5RRTR555465",
fv: "FV/12344/2019"
},
{
key: 2,
model: "2222222",
sn: "TERR5RRTR555465",
fv: "FV/12344/2019"
},
{
key: 3,
model: "33333",
sn: "TERR5RRTR555465",
fv: "FV/12344/2019"
},
{
key: 4,
model: "44444444",
sn: "TERR5RRTR555465",
fv: "FV/12344/2019"
}
Rows have button to remove row from table. After double click, row is removed from data, but on page is removed only last row from table. And if I remove another one random row, on page is remove always last row table.
Where is problem and what I don't understand in REACT?
My REACT example:
https://codesandbox.io/embed/react-table-array-99xiq
and code:
import React from "react";
import { Button, Form, Input, Message, Table } from "semantic-ui-react";
import "./styles.css";
import "semantic-ui-css/semantic.min.css";
export default class App extends React.Component {
constructor() {
super();
this.state = {
lista: [
{
key: 1,
model: "11111111",
sn: "TERR5RRTR555465",
fv: "FV/12344/2019"
},
{
key: 2,
model: "2222222",
sn: "TERR5RRTR555465",
fv: "FV/12344/2019"
},
{ key: 3, model: "33333", sn: "TERR5RRTR555465", fv: "FV/12344/2019" },
{
key: 4,
model: "44444444",
sn: "TERR5RRTR555465",
fv: "FV/12344/2019"
},
{ key: 5, model: "5555555", sn: "TERR5RRTR555465", fv: "FV/12344/2019" }
]
};
this.toDoChangeValues = this.toDoChangeValues.bind(this);
this.removeListIndex = this.removeListIndex.bind(this);
}
toDoChangeValues(n, v) {
var nam = n.split("_");
var list = this.state.lista;
var indx = list.findIndex(x => x.key == nam[1]);
list[indx][nam[0]] = v;
this.setState({ lista: list });
}
removeListIndex(n) {
this.setState(prevState => ({
lista: prevState.lista.filter(row => row.key != n)
}));
}
render() {
if (
this.state.lista.find(function(x) {
return x.model === "" && x.sn === "" && x.fv === "";
}) === undefined
) {
var new_id = Math.max.apply(null, [
...this.state.lista.map(function(o) {
return o.key;
}),
0
]);
this.setState({
lista: [
...this.state.lista,
{ key: new_id + 1, model: "", sn: "", fv: "" }
]
});
}
const { lista } = this.state;
return (
<>
<div className="segm_space">
<Message attached header="Table list" />
<Form className="attached fluid segment">
<Table
basic="very"
celled
compact
className="list_hardwares"
unstackable
>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Data</Table.HeaderCell>
<Table.HeaderCell>Number</Table.HeaderCell>
<Table.HeaderCell>Type</Table.HeaderCell>
<Table.HeaderCell style={{ width: "1%" }} />
</Table.Row>
</Table.Header>
<Table.Body>
{lista.map(
function(object) {
return (
<RowData
obj={object}
rmveIndx={this.removeListIndex}
chVal={this.toDoChangeValues}
/>
);
}.bind(this)
)}
</Table.Body>
</Table>
</Form>
</div>
</>
);
}
}
export class RowData extends React.Component {
constructor() {
super();
this.state = {
trash: false
};
this.onTodoChange = this.onTodoChange.bind(this);
this.onTrash = this.onTrash.bind(this);
}
onTodoChange(e) {
const { name, value } = e.target;
this.props.chVal(name, value);
}
onTrash(e) {
if (!this.state.trash) {
this.setState({ trash: true }, () => {
setTimeout(
function() {
this.setState({ trash: false });
}.bind(this),
2000
);
});
} else {
this.props.rmveIndx(e.target.name || e.target.closest("button").name);
}
}
render() {
return (
<Table.Row id={"id_" + this.props.obj.key}>
<Table.Cell>
<Input
fluid
transparent
onChange={this.onTodoChange}
name={"model_" + this.props.obj.key}
placeholder="00000000000"
defaultValue={this.props.obj.model}
/>
</Table.Cell>
<Table.Cell>
<Input
fluid
transparent
onChange={this.onTodoChange}
name={"sn_" + this.props.obj.key}
placeholder="XXXXXXXXXXXXXXX"
defaultValue={this.props.obj.sn}
/>
</Table.Cell>
<Table.Cell>
<Input
fluid
transparent
onChange={this.onTodoChange}
defaultValue={this.props.obj.fv}
/>
</Table.Cell>
<Table.Cell>
<Button
name={this.props.obj.key}
onClick={this.onTrash}
color={this.state.trash ? "blue" : undefined}
compact
size="tiny"
icon="trash"
/>
</Table.Cell>
</Table.Row>
);
}
}
import React from "react";
import { Button, Form, Input, Message, Table } from "semantic-ui-react";
import "./styles.css";
import "semantic-ui-css/semantic.min.css";
export default class App extends React.Component {
constructor() {
super();
this.state = {
inputFocus: null,
lista: [
{
key: 1,
model: "11111111",
sn: "TERR5RRTR555465",
fv: "FV/12344/2019"
},
{
key: 2,
model: "2222222",
sn: "TERR5RRTR555465",
fv: "FV/12344/2019"
},
{ key: 3, model: "33333", sn: "TERR5RRTR555465", fv: "FV/12344/2019" },
{
key: 4,
model: "44444444",
sn: "TERR5RRTR555465",
fv: "FV/12344/2019"
},
{ key: 5, model: "5555555", sn: "TERR5RRTR555465", fv: "FV/12344/2019" }
]
};
}
handleChange = (value,name,id) => {
const {lista} = this.state;
const newData = [...lista.filter(item => item.key !== id), { ...lista.filter(item => item.key === id)[0], [name]: value}];
this.setState({lista: newData});
}
addData = () => {
const {lista} = this.state;
this.setState({ lista: [...lista, { key: lista[lista.length - 1].key + 1, model: this.model.inputRef.current.value, sn: this.sn.inputRef.current.value, fv: this.fv.inputRef.current.value}]});
this.model.inputRef.current.value = '';
this.sn.inputRef.current.value = '';
this.fv.inputRef.current.value = '';
}
trash = (id) => {
this.setState({lista: this.state.lista.filter(item => item.key !== id)});
}
render() {
const { lista } = this.state;
return (
<>
<div className="segm_space">
<Message attached header="Table list" />
<Form className="attached fluid segment">
<Table
basic="very"
celled
compact
className="list_hardwares"
unstackable
>
<Table.Header>
<Table.Row>
<Table.HeaderCell>Data</Table.HeaderCell>
<Table.HeaderCell>Number</Table.HeaderCell>
<Table.HeaderCell>Type</Table.HeaderCell>
<Table.HeaderCell style={{ width: "1%" }} />
</Table.Row>
</Table.Header>
<Table.Body>
{lista.sort((prev,next) => {
if (prev.key > next.key) return 1;
return -1;
}).map(item => <Table.Row key={item.key}>
<Table.Cell>
<Input
fluid
transparent
name='model'
onChange={(e,data) => this.handleChange(data.value,data.name, item.key)}
placeholder="00000000000"
defaultValue={item.model}
/>
</Table.Cell>
<Table.Cell>
<Input
fluid
transparent
name='sn'
onChange={(e, data) => this.handleChange(data.value, data.name, item.key)}
placeholder="XXXXXXXXXXXXXXX"
defaultValue={item.sn}
/>
</Table.Cell>
<Table.Cell>
<Input
fluid
transparent
name='fv'
onChange={(e, data) => this.handleChange(data.value, data.name, item.key)}
defaultValue={item.fv}
/>
</Table.Cell>
<Table.Cell>
<Button
onClick={() => this.trash(item.key)}
compact
size="tiny"
icon="trash"
/>
</Table.Cell>
</Table.Row>)}
<Table.Row>
<Table.Cell>
<Input
fluid
transparent
name='model'
ref={n => this.model = n}
placeholder="00000000000"
/>
</Table.Cell>
<Table.Cell>
<Input
fluid
transparent
name='sn'
ref={n => this.sn = n}
placeholder="XXXXXXXXXXXXXXX"
/>
</Table.Cell>
<Table.Cell>
<Input
fluid
transparent
name='fv'
ref={n => this.fv = n}
/>
</Table.Cell>
<Table.Cell>
<Button
compact
size="tiny"
icon="add"
onClick={this.addData}
/>
</Table.Cell>
</Table.Row>
</Table.Body>
</Table>
</Form>
</div>
</>
);
}
}
There are few bugs in the code : 1. You dont need to setState inside render function.
//Your Code
this.setState({
lista: [
...this.state.lista,
{ key: new_id + 1, model: "", sn: "", fv: "" }
]
});
this.props.rmveIndx(e.target.name || e.target.closest("button").name);
to (You dont need it. You can simply do this )
onTrash(e) {
this.props.rmveIndx();
}
{lista.map(object => <RowData
obj={object}
rmveIndx={() => this.removeListIndex(object)} //Note here
chVal={this.toDoChangeValues}
/>)
removeListIndex(n) {
this.setState(prevState => ({
lista: prevState.lista.filter(row => row.key !== n.key)
}));
}
<Table.Row id={"id_" + this.props.obj.key}>
<Table.Cell>
<Input
fluid
transparent
onChange={this.onTodoChange}
name={"model_" + this.props.obj.key}
placeholder="00000000000"
defaultValue={this.props.obj.model}
value={this.props.obj.model}
/>
</Table.Cell>
<Table.Cell>
<Input
fluid
transparent
onChange={this.onTodoChange}
name={"sn_" + this.props.obj.key}
placeholder="XXXXXXXXXXXXXXX"
defaultValue={this.props.obj.sn}
value={this.props.obj.sn}
/>
</Table.Cell>
<Table.Cell>
<Input
fluid
transparent
onChange={this.onTodoChange}
defaultValue={this.props.obj.fv}
value={this.props.obj.fv}
/>
</Table.Cell>
<Table.Cell>
<Button
name={this.props.obj.key}
onClick={this.onTrash}
color={this.state.trash ? "blue" : undefined}
compact
size="tiny"
icon="trash"
/>
</Table.Cell>
</Table.Row>
Here is working code sandbox link : https://codesandbox.io/s/react-table-array-rinfw
Note : I commented some of your code. It just logic to guide how it works in it. you can comment and carry your code from here
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.