简体   繁体   English

在React.js中将密钥传递给子项

[英]Passing keys to children in React.js

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. 我正在运行有关tutsplus的反应教程,这个教程有点旧,而且代码不像最初编写的那样工作。 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 首先,如果你想运行这个代码并在运行中看到它,那么就是repo: 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: 现在当有人点击投票按钮时,FeedItem.vote()方法的所需行为是将对象发送到主Feed组件:

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: 哪个应该通过父组件的onVote函数传递该键:

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. 我的逻辑依赖于能够协调onVote函数中的键,但是关键道具没有被正确传递。 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 . key道具在React中具有特殊含义 It it is not passed to the component as prop but is used by React to aid the reconciliation of collections. 它不作为prop传递给组件,但React使用它来帮助集合的协调。 If you know d3 , it works similar like the key function for selection.data() . 如果你知道d3 ,它的工作方式类似于selection.data()的关键功能。 It allows React to associate the elements of the previous tree with the elements of the next tree. 它允许React将前一个树的元素与下一个树的元素相关联。

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: 你有一把key是好的(如果你传递一个元素数组你需要一个),但如果你想将该值传递给组件,你应该另一个道具:

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

(and access this.props.id inside the component). (并在组件中访问this.props.id )。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM