Answer the question
In order to leave comments, you need to log in
How do state relationships work in react js?
I'm just learning about react and I can't figure out how react operates on state. This component renders a simple table with each row corresponding to one node. When you click on the edit button in one of the rows, the corresponding node is copied to the selected_node, and another row is shown with an input that changes the selected_node. But for some reason, after the change, when canceling editing (erasing selected_node), the original state.nodes is already changed, and after pressing cancel, the initial table becomes changed.
In short - how to make it so that when editing one selected_node, the general state.nodes does not change
import React from 'react';
export default class TestPage extends React.Component {
constructor(props) {
super(props);
this.state = {
nodes: [
{id: 1, content: "qwerty"},
{id: 2, content: "abcdef"}
],
selected_node: {}
};
}
cancelEdit() {
this.setState({selected_node: {}});
}
selectNode(node) {
this.setState({selected_node: node});
}
handleContent(event) {
let selected_node = this.state.selected_node;
selected_node.content = event.target.value;
this.setState({selected_node: selected_node});
}
render() {
let self = this;
return (
<div>
<table>
<thead>
<th>id</th>
<th>content</th>
<th>edit</th>
</thead>
<tbody>
{this.state.nodes.map(function(node, i) {
if(node.id == self.state.selected_node.id) {
return <tr key={i}>
<td>{node.id}</td>
<td><input
value={self.state.selected_node.content}
onChange={self.handleContent.bind(self)}
/>
</td>
<td>
<button>save</button>
<button onClick={self.cancelEdit.bind(self)}>cancel</button>
</td>
</tr>
} else {
return <tr key={i}>
<td>{node.id}</td>
<td>{node.content}</td>
<td><button onClick={self.selectNode.bind(self, node)}>edit</button></td>
</tr>;
}
})}
</tbody>
</table>
</div>
);
}
};
Answer the question
In order to leave comments, you need to log in
You in selectNode assign not the contents of the object, but a link to it, and then you make changes to the object using this link.
so if you do something like this:
selectNode(node) {
let nodeNew = Object.assign({}, node)
this.setState({selected_node: nodeNew});
}
import React, { Component } from 'react'
export default class TestPage extends Component {
constructor(props) {
super(props);
this.input = null
this.state = {
nodes: [
{ id: 1, content: "qwerty", edit: false },
{ id: 2, content: "abcdef", edit: false }
],
inputVal: ''
};
}
toggleEdit(id, isEdit) {
this.setState({
...this.state,
nodes: this.state.nodes.map(n => {
if( n.id === id ) {
n.edit = isEdit
}
return n
})
})
}
handleContent(event) {
....
}
render() {
return (
<div>
<table>
<thead>
<th>id</th>
<th>content</th>
<th>edit</th>
</thead>
<tbody>
{this.state.nodes.map((node) => {
if(node.edit) {
return <tr key={node.id}>
<td>{node.id}</td>
<td><input
onChange={this.handleContent.bind(this)}
ref={(input) => this.input = input}
value={this.state.inputVal}
/>
</td>
<td>
<button type="submit">save</button>
<button onClick={() => this.toggleEdit(node.id, false)}>cancel</button>
</td>
</tr>
} else {
return <tr key={node.id}>
<td>{node.id}</td>
<td>{node.content}</td>
<td><button onClick={() => this.toggleEdit(node.id, true)}>edit</button></td>
</tr>;
}
})}
</tbody>
</table>
</div>
);
}
};
Didn't find what you were looking for?
Ask your questionAsk a Question
731 491 924 answers to any question