【问题标题】:React update state on click点击时反应更新状态
【发布时间】:2016-06-15 07:31:31
【问题描述】:

我有一个小组件,它列出了如下所示的数据结构。我想要做的是当我单击update 按钮时我想增加vote 键,但是,我没有找到正确的方法。我需要更新整个data 状态吗?我对此没有什么困惑。

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;

阅读答案后,我的最终结果如下所示,效果很好。还是谢谢。

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

  }

【问题讨论】:

    标签: javascript reactjs react-router


    【解决方案1】:

    在这种情况下,我会将onClick 处理程序添加到LinksPage 组件。

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

    并更改您的 update 函数:

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

    【讨论】:

    • 是否需要遍历this.state.data 才能找到实际数据?
    • 嗯,你可以,但是,你可能知道,你不应该改变状态。我认为最好的更新方法是: // find index by id const itemIndex = this.state.data.findIndex(c => c.id === id); // 创建一个新数组 const data = [ ...nodes.slice(0, itemIndex ), Object.assign({}, this.state.data[itemIndex ], { value: value + 1, }), .. .nodes.slice(itemIndex + 1), ];
    • 或者你可以使用Array.map函数进行迭代。
    【解决方案2】:

    将链接 ID 传递给 LinkListPage 组件中的更新方法。 参考点阅读此内容以处理更新以加深理解https://www.sitepoint.com/immutability-javascript/

    在 update 方法中使用 immutablejs 或 es6 导致状态在 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>
      );
    };

    【讨论】:

      【解决方案3】:

      我会为此使用生命周期挂钩,因为 onClick 事件对组件状态有副作用。

      当我尝试聆听画布上的每一次点击时,您可以看看这个示例,因为我使用了 componentDidUpdate() 方法。

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

      你可以试试这个 sn-p 看看我们是否改变了 console.log() 函数你会发现它需要两次点击才能看到正确的协调。

      【讨论】:

        猜你喜欢
        • 2018-08-11
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-30
        • 1970-01-01
        • 1970-01-01
        • 2022-01-23
        相关资源
        最近更新 更多