agriboz agriboz - 5 months ago 25
Javascript Question

React update state on click

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});

}

Answer

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,
    });
  }
}
Comments