2015-05-26 14 views
7

Tôi đang chạy qua hướng dẫn phản ứng trên tutsplus cũ một chút và mã không hoạt động như ban đầu được viết. Tôi thực sự là hoàn toàn ok với điều này vì nó buộc tôi phải học độc lập hơn, tuy nhiên tôi đã dành một thời gian trên một lỗi mà tôi chỉ không thể tìm ra. Lỗi này bao gồm việc không thể truyền vào một khóa đối tượng, điều này ngăn cản chương trình của tôi cập nhật trạng thái của đối tượng chính xác.Truyền chìa khóa cho trẻ em trong React.js

Trước hết đây là repo nếu bạn muốn chạy mã này và xem nó trong hành động: https://github.com/camerow/react-voteit

Tôi có một thành phần con trông như thế này:

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

}); 

Bây giờ khi ai đó chạm nút bỏ phiếu hành vi mong muốn là dành cho phương thức FeedItem.vote() để gửi một đối tượng đến thành phần Nguồn cấp dữ liệu chính:

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

}); 

Điều gì sẽ vượt qua khóa đó trên Thr nên chức năng onVote của thành phần gốc:

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

}); 

Logic của tôi dựa vào việc có thể hòa hợp các phím trong chức năng onVote, tuy nhiên, khóa chính không được truyền chính xác. Vì vậy, câu hỏi của tôi là, làm thế nào để tôi vượt qua trên chính họ thông qua 'một cách dòng chảy' để thành phần cha mẹ của tôi?

Lưu ý: Vui lòng chỉ ra các vấn đề khác hoặc quyết định thiết kế tốt hơn, hoặc những điều ngu ngốc tuyệt đối. Hoặc thậm chí tôi hỏi câu hỏi sai.

Mong được khám phá tốt đẹp khung làm việc thú vị này.

+2

'khóa' có ý nghĩa đặc biệt trong Phản hồi. Nó không được cung cấp cho thành phần thông qua 'this.props.key' afaik. Bạn nên sử dụng một tên prop khác cho điều đó. Hoặc, nếu bạn thực sự muốn sử dụng giá trị làm khóa, hãy thêm một giá trị bổ sung giống nhau, sau đó bạn có thể truy cập vào bên trong thành phần. Xem https://facebook.github.io/react/docs/multiple-components.html#dynamic-children –

+0

Ahh, ok, điều đó đã giúp ích rất nhiều. Tôi đã đọc tài liệu đó nhưng có một chút bối rối. Vì vậy, để làm rõ nó ok cho tôi để xác định một prop 'chìa khóa' nhưng nó sẽ giống như' '? Hoặc tôi có nên tránh 'khóa 'hoàn toàn không? – camerow

+0

Vẫn nhận được cảnh báo này 'Cảnh báo: Mỗi trẻ trong một mảng hoặc trình lặp nên có một khóa" chìa khóa "duy nhất. Kiểm tra phương thức render của FeedList. Xem https://fb.me/react-warning-keys để biết thêm thông tin.', mặc dù thay đổi tất cả các thể hiện của 'key' thành' id' cho phép tôi vượt qua mệnh đề đó. – camerow

Trả lời

28

The key prop has a special meaning in React. Nó không được chuyển đến thành phần như prop nhưng được sử dụng bởi React để hỗ trợ cho việc hòa giải các bộ sưu tập. Nếu bạn biết d3, nó hoạt động tương tự như chức năng chính cho selection.data(). Nó cho phép React kết hợp các phần tử của cây trước đó với các phần tử của cây tiếp theo.

Thật tốt khi bạn có một key (và bạn cần một nếu bạn vượt qua một loạt các yếu tố), nhưng nếu bạn muốn vượt qua giá trị mà cùng với thành phần, bạn nên một prop:

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

(và truy cập this.props.id bên trong thành phần).

+1

Cảm ơn bạn. Điều này giải quyết vấn đề keying của tôi, bây giờ tôi chỉ cần sửa logic trong hàm 'onVote' của tôi. – camerow

+0

Cảm ơn rất nhiều @Felix. BTW, bạn có thể giúp với câu hỏi này không? Tôi muốn chuyển nút dưới dạng thuộc tính theo cách Phản hồi: http://stackoverflow.com/questions/34879973/pass-this-refs-as-property-in-jsx-in-react-js – haotang

Các vấn đề liên quan