Reputation: 501
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>
);
}
}
Upvotes: 0
Views: 1448
Reputation: 255
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>
</>
);
}
}
Upvotes: 1
Reputation: 5054
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
Upvotes: 0