I have small component which lists data structure as shown below. What i want to do is when i click the update
button i want to increment vote
key, however, i didn't find a way to do it properly. Do i need to update the whole data
state? I have little confuse on it.
let MOCKDATA = [
{
id: 1,
name: 'Test 1',
vote: 0
},
{
id: 2,
name: 'Test 2',
vote: 2
}];
LinkListPage.js
import React from 'react';
// import LinksData from '../LinksData';
import Links from './Links';
// import update from 'react-addons-update';
//localStorage.setItem('linksData', JSON.stringify(LinksData));
let MOCKDATA = [
{
id: 1,
name: 'Test 1',
vote: 0
},
{
id: 2,
name: 'Test 2',
vote: 2
}];
class LinkListPage extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
data: MOCKDATA
};
this.update = this.update.bind(this);
}
componentDidMount() {
}
update() {
// this.setState({
// data:
// })
}
render() {
let list = this.state.data.map( links => {
return <Links key={links.id} update={this.update} data={links} />;
});
return (
<div>
<ul>{list}</ul>
{console.log(this.state.data)}
</div>
);
}
}
export default LinkListPage;
LinksPage.js
import React, {PropTypes} from 'react';
const Links = (props) => {
return (
<li>
<p>{props.data.name}</p>
<p>{props.data.vote}</p>
<button onClick={props.update}>Up</button>
</li>
);
};
Links.propTypes = {
data: PropTypes.object,
name: PropTypes.string,
vote: PropTypes.number,
update: PropTypes.func
};
export default Links;
HomePage.js
import React from 'react';
import LinkListPage from '../containers/LinkListPage';
const HomePage = () => {
return (
<div>
<LinkListPage />
</div>
);
};
export default HomePage;
After reading the answers my final result is as below which works fine. Thanks anyway.
LinksPage.js
const Links = (props) => {
return (
<li>
<p>{props.data.name}</p>
<p>{props.data.vote}</p>
<button onClick={() => props.update(props.data.id)}>Up</button>
</li>
);
};
LinkListPage.js
update(id) {
const findId = LinksData.filter(item => {
item.id === id ? item.vote++ : false;
});
const data = Object.assign(...findId, LinksData);
this.state.data.sort((a, b) => {
return b.vote - a.vote;
});
//localStorage.setItem('linksData', JSON.stringify(this.state.data));
this.setState({data});
}
We have to set initial state value inside constructor function and set click event handler of the element upon which click, results in changing state. Then pass the function to the click handler and change the state of the component inside the function using setState.
To update a component's state on click, add an onClick prop to an element and set it to a function. The function will be invoked every time the element is clicked, which allows us to update the component's state on click.
To update our state, we use this. setState() and pass in an object. This object will get merged with the current state. When the state has been updated, our component re-renders automatically.
One should never update the state directly because of the following reasons: If you update it directly, calling the setState() afterward may just replace the update you made. When you directly update the state, it does not change this.
In this case, I would add onClick
handler to LinksPage
component.
class Links extends React.Component {
constructor(props) {
super(props);
this.onClick = this.onClick.bind(this);
}
onClick(e) {
// here you know which component is that, so you can call parent method
this.props.update(this.props.data.id);
}
render() {
return (
<li>
<p>{this.props.data.name}</p>
<p>{this.props.data.vote}</p>
<button onClick={this.onClick}>Up</button>
</li>
);
}
};
And change your update
function:
class LinkListPage extends React.Component {
constructor(props, context) {
super(props, context);
this.state = {
data: MOCKDATA
};
this.update = this.update.bind(this);
}
update(itemId) {
// TODO: find and update your item, you can do it since you have an 'id'
const data = [...];
this.setState({
data,
});
}
}
pass link id to update method in the LinkListPage component. ref point read this for handling the update for deep understanding https://www.sitepoint.com/immutability-javascript/
use immutablejs or es6 in the update method cause state is immutable in react
update(id) {
//find and update your item, you can do it since you have an 'id'
//follow link: http://codereview.stackexchange.com/questions/43438/writing-a-function-to-add-or-modify-an-existing-object-inside-an-array
// this.setState({
// data:
// })
}
const Links = (props) => {
return (
<li>
<p>{props.data.name}</p>
<p>{props.data.vote}</p>
<button onClick={() => props.update(props.id)}>Up</button>
</li>
);
};
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With