Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

  }
like image 815
agriboz Avatar asked Jun 15 '16 07:06

agriboz


People also ask

How do I change my state on click in React?

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.

How do you update a click React component?

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.

How do I update states in React?

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.

Can we directly update state in React?

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.


2 Answers

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,
    });
  }
}
like image 101
Ross Khanas Avatar answered Oct 15 '22 20:10

Ross Khanas


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>
  );
};
like image 2
Mike Tronic Avatar answered Oct 15 '22 22:10

Mike Tronic