最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - React update state on click - Stack Overflow

programmeradmin12浏览0评论

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

  }

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

  }
Share Improve this question edited Jun 22, 2016 at 7:31 agriboz asked Jun 15, 2016 at 7:31 agribozagriboz 4,8544 gold badges36 silver badges49 bronze badges
Add a comment  | 

3 Answers 3

Reset to default 7

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

I would use a lifecycle hook for that as onClick event have side-effects on the component state.

you may have a look at this example as i try to listen to every click on the canvas, for that i used componentDidUpdate() method.

class Canvas extends Component {
  state = {
    drawing: false,
    x: 0,
    y: 0,
  };

  componentDidUpdate() {
    // this will log after every click on canvas
    console.log(this.state.drawing, this.state.x, this.state.y);
  }

  mouseDownHandler = (e) => {
    this.setState({
      drawing: true,
      x: e.clientX,
      y: e.clientY,
    });
  };

  render() {
    return (
      <div>
        <canvas
          onMouseDown={this.mouseDownHandler}
          ref="canvas"
          width={640}
          height={425}
        ></canvas>
      </div>
    );
  }
}

you can try this snippet and have a look if we changed the console.log() function you will find it will need two clicks to see correct coordination.

发布评论

评论列表(0)

  1. 暂无评论