在 React.js 中将密钥传递给孩子 [英] Passing keys to children in React.js

查看:23
本文介绍了在 React.js 中将密钥传递给孩子的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在浏览一个关于 tutsplus 的 React 教程,它有点旧,并且代码无法像最初编写的那样工作.我实际上对此完全没问题,因为它迫使我更加独立地学习,但是我花了一段时间解决了一个我无法弄清楚的错误.该错误包括无法传递对象键,这会阻止我的程序更新正确对象的状态.

如果您想运行此代码并查看它的实际效果,首先这里是 repo:https://github.com/camerow/react-voteit

我有一个如下所示的子组件:

var FeedItem = React.createClass({投票:功能(新计数){console.log("Voting on: ", this.props, " 这应该有一个关联的键.");this.props.onVote({密钥:this.props.key,标题:this.props.title,描述:this.props.desc,投票计数:新计数});},投票:函数(){var count = parseInt(this.props.voteCount, 10);var newCount = 计数 + 1;this.vote(newCount);},投票:功能(){var count = parseInt(this.props.voteCount, 10);var newCount = 计数 - 1;this.vote(newCount);},渲染:函数(){var positiveNegativeClassName = this.props.voteCount >= 0 ?'徽章徽章-成功':'徽章徽章-危险';返回 (<li key={this.props.key} className="list-group-item"><span className={positiveNegativeClassName}>{this.props.voteCount}</span><h4>{this.props.title}</h4><span>{this.props.desc}</span><span className="pull-right"><button id="up" className="btn btn-sm btn-primary" onClick={this.voteUp}>&uarr;</button><button id="down" className="btn btn-sm btn-primary" onClick={this.voteDown}>&darr;</button></span>);}});

现在,当有人点击投票按钮时,所需的行为是 FeedItem.vote() 方法将对象发送到主 Feed 组件:

var FeedList = React.createClass({渲染:函数(){var feedItems = this.props.items;返回 (<div className="容器"><ul className="list-group">{feedItems.map(function(item) {return }.bind(this))}

);}});

哪个应该通过父组件的 onVote 函数传递该键:

var Feed = React.createClass({getInitialState: 函数 () {var FEED_ITEMS = [{关键:1,title: 'JavaScript 很有趣',描述:'词法范围FTW',投票数:34}, {关键:2,title: '实时数据!',描述:'Firebase 很酷',投票数:49}, {关键:3,title: '咖啡让你清醒',描述:'负责任地饮酒',投票数:15}];返回 {项目:FEED_ITEMS,表格显示:假}},onToggleForm: 函数 () {this.setState({formDisplayed: !this.state.formDisplayed});},onNewItem: 函数 (newItem) {var newItems = this.state.items.concat([newItem]);//console.log("创建这些项目:", newItems);this.setState({项目:新项目,表格显示:假,关键:this.state.items.length});},onVote: 函数 (newItem) {//console.log(item);var items = _.uniq(this.state.items);var index = _.findIndex(items, function (feedItems) {//没有得到正确的索引.console.log("Does", feedItems.key, " === ", newItem.key, "?");返回 feedItems.key === newItem.key;});var oldObj = items[index];var newItems = _.pull(items, oldObj);var newItems = this.state.items.concat([newItem]);//newItems.push(item);this.setState({项目:新项目});},渲染:函数(){返回 (<div><div className="容器"><ShowAddButton 显示={this.state.formDisplayed} onToggleForm={this.onToggleForm}/>

<FeedForm 显示={this.state.formDisplayed} onNewItem={this.onNewItem}/><br/><br/><FeedList items={this.state.items} onVote={this.onVote}/>

);}});

我的逻辑依赖于能够协调 onVote 函数中的键,但是键道具没有被正确传递.所以我的问题是,我如何通过这种单向流"将它们的键传递给我的父组件?

注意:请随意指出其他问题或更好的设计决策,或绝对愚蠢的地方.或者甚至我问错了问题.

期待对这个很酷的框架有一个很好的探索.

解决方案

key prop 在 React 中有着特殊的意义.它不会作为 prop 传递给组件,而是被 React 用来帮助协调集合.如果您知道 d3,它的工作原理类似于 selection.data() 的关键函数.它允许 React 将前一棵树的元素与下一棵树的元素相关联.

你有一个 key 很好(如果你传递一个元素数组,你需要一个),但是如果你想把那个值传递给组件,你应该另一个道具:

(并访问组件内的 this.props.id).

I am running through a react tutorial on tutsplus that is a bit old, and the code doesn't work as it was originally written. I actually am totally ok with this as it forces me to learn more independently, however I have spent a while on a bug that I just can't figure out. The bug consists of not being able to pass on an objects key, which prevents my program from updating the state of the correct object.

First off here is the repo if you want to run this code and see it in action: https://github.com/camerow/react-voteit

I have a child component that looks like this:

var FeedItem = React.createClass({

  vote: function(newCount) {
    console.log("Voting on: ", this.props, " which should have a key associated.");

    this.props.onVote({
      key: this.props.key,
      title: this.props.title,
      description: this.props.desc,
      voteCount: newCount
    });
  },

  voteUp: function() {
    var count = parseInt(this.props.voteCount, 10);
    var newCount = count + 1;
    this.vote(newCount);
  },

  voteDown: function() {
    var count = parseInt(this.props.voteCount, 10);
    var newCount = count - 1;
    this.vote(newCount);
  },

  render: function() {
    var positiveNegativeClassName = this.props.voteCount >= 0 ?
                                    'badge badge-success' :
                                    'badge badge-danger';
    return (
      <li key={this.props.key} className="list-group-item">
        <span className={positiveNegativeClassName}>{this.props.voteCount}</span>
        <h4>{this.props.title}</h4>
        <span>{this.props.desc}</span>
        <span className="pull-right">
          <button id="up" className="btn btn-sm btn-primary" onClick={this.voteUp}>&uarr;</button>
          <button id="down" className="btn btn-sm btn-primary" onClick={this.voteDown}>&darr;</button>
        </span>
      </li>
    );
  }

});

Now when someone hits the vote button the desired behavior is for the FeedItem.vote() method to send an object up to the main Feed component:

var FeedList = React.createClass({

  render: function() {
    var feedItems = this.props.items;

    return (
      <div className="container">
        <ul className="list-group">

          {feedItems.map(function(item) {
            return <FeedItem key={item.key}
                             title={item.title}
                             desc={item.description}
                             voteCount={item.voteCount}
                             onVote={this.props.onVote} />
          }.bind(this))}
        </ul>
      </div>
    );
  }

});

Which should pass that key on throught the parent component's onVote function:

var Feed = React.createClass({

  getInitialState: function () {
    var FEED_ITEMS = [
      {
        key: 1,
        title: 'JavaScript is fun',
        description: 'Lexical scoping FTW',
        voteCount: 34
      }, {
        key: 2,
        title: 'Realtime data!',
        description: 'Firebase is cool',
        voteCount: 49
      }, {
        key: 3,
        title: 'Coffee makes you awake',
        description: 'Drink responsibly',
        voteCount: 15
      }
    ];
    return {
      items: FEED_ITEMS,
      formDisplayed: false
    }
  },

  onToggleForm: function () {
    this.setState({
      formDisplayed: !this.state.formDisplayed
    });
  },

  onNewItem: function (newItem) {
    var newItems = this.state.items.concat([newItem]);
    // console.log("Creating these items: ", newItems);
    this.setState({
      items: newItems,
      formDisplayed: false,
      key: this.state.items.length
    });
  },

  onVote: function (newItem) {
    // console.log(item);

    var items = _.uniq(this.state.items);
    var index = _.findIndex(items, function (feedItems) {
      // Not getting the correct index.
      console.log("Does ", feedItems.key, " === ", newItem.key, "?");
      return feedItems.key === newItem.key;
    });
    var oldObj = items[index];
    var newItems = _.pull(items, oldObj);
    var newItems = this.state.items.concat([newItem]);
    // newItems.push(item);
    this.setState({
      items: newItems
    });
  },

  render: function () {
    return (
      <div>
        <div className="container">
          <ShowAddButton displayed={this.state.formDisplayed} onToggleForm={this.onToggleForm}/>
        </div>
        <FeedForm displayed={this.state.formDisplayed} onNewItem={this.onNewItem}/>
        <br />
        <br />
        <FeedList items={this.state.items} onVote={this.onVote}/>
      </div>
    );
  }

});

My logic relies on being able to reconcile the keys in the onVote function, however the key prop is not being properly passed on. So my question is, how do I pass on they key through this 'one way flow' to my parent component?

Note: Feel free to point out other problems or better design decision, or absolute stupidities. Or even that I'm asking the wrong question.

Looking forward to a nice exploration of this cool framework.

解决方案

The key prop has a special meaning in React. It it is not passed to the component as prop but is used by React to aid the reconciliation of collections. If you know d3, it works similar like the key function for selection.data(). It allows React to associate the elements of the previous tree with the elements of the next tree.

It's good that you have a key (and you need one if you pass an array of elements), but if you want to pass that value along to the component, you should another prop:

<FeedItem key={item.key} id={item.key} ... />

(and access this.props.id inside the component).

这篇关于在 React.js 中将密钥传递给孩子的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
相关文章
前端开发最新文章
热门教程
热门工具
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆