2017-03-10 4 views
3

ネストされた配列のセットに反応してアイテムを適切にレンダリングすることに気付きましたが、この方法では、key私の要素に。フラットアレイとネストされた配列のリアクションが異なるように処理される

const stuff = 'a,b,c'; 

// Nested Array 
// React is fine with it and automatically assigns keys 
// Sample data: [[a, <br />], [b, <br />], [c, <br />]] 
const Foo =() => <div>{stuff.split(',').map(itm => [itm, <br />])}</div>; 

// Flat Array 
// React warns me that I should assign a key to each element in array 
// Sample data: [a, <br />, b, <br />, c, <br />] 
const Bar =() => <div>{stuff.split(',').map(itm => [itm, <br />]).reduce((a, b) => a.concat(b), [])}</div>; 

サンプルペン:

https://codepen.io/FezVrasta/pen/NppLPR

なぜそれが起こるのでしょうか? Reactの "ネストされた配列"サポートへの参照や "自動割り当てされたキー"の参照が見つかりません。

+0

子供の配列の場合、[キー付きフラグメント](https://facebook.github.io/react/docs/create-fragment.html)を使用してください。ドキュメントはネイティブ配列に 'key'属性を追加することは不可能であることを認識し、それらを処理するために' 'react-addons-create-fragment''パッケージを提供します。 –

答えて

4

コンソールに警告が表示されても、ReactはHTML内のFooBarの両方が生成されていることを示しています。リアクションは、レンダリングのパフォーマンスを向上させようとする際に、調整のためにユニークなキーを使用します。この詳細についてはReact reconciliation recursing on childrenページをご覧ください。鍵を提供していないということは、Reactは、それが設計されているほどパフォーマンスが悪いということを意味します。

警告がネストされた配列のコンソールに出力されていない理由として、あなたの質問に関して

、我々はソースコードに飛び込む必要があります:

validateExplicitKeyと呼ばれ、警告を生成し、に住んでいる機能ReactElementValidator.jsモジュール。

この関数は同じモジュールでvalidateChildKeysで使用される - ソースコードに探しが反応15.4.2のように、次のように与える:

function validateChildKeys(node, parentType) { 
    if (typeof node !== 'object') { 
    return; 
    } 
    if (Array.isArray(node)) {      // 1. 
    for (var i = 0; i < node.length; i++) { 
     var child = node[i];      // 2. 
     if (ReactElement.isValidElement(child)) { // 3. 
     validateExplicitKey(child, parentType); 
     } 
    } 
    } else if (ReactElement.isValidElement(node)) { 
    // This element was passed in a valid location. 
    if (node._store) { 
     node._store.validated = true; 
    } 
    } else if (node) { 
    var iteratorFn = getIteratorFn(node); 
    // Entry iterators provide implicit keys. 
    if (iteratorFn) { 
     if (iteratorFn !== node.entries) { 
     var iterator = iteratorFn.call(node); 
     var step; 
     while (!(step = iterator.next()).done) { 
      if (ReactElement.isValidElement(step.value)) { 
      validateExplicitKey(step.value, parentType); 
      } 
     } 
     } 
    } 
    } 
} 
  1. 配列の配列は、最初のコードを入力しますchildchild = ["b", Object]に設定されます
  2. ブロック
  3. (「オブジェクトが」brノード用の仮想DOM表現を反応させている、我々はJSX経由で作成しました)配列は、機能ReactElement.isValidElementを介して実行されます。

    として設定されているREACT_ELEMENT_TYPE
    ReactElement.isValidElement = function (object) { 
        return typeof object === 'object' && object !== null && object.$$typeof === REACT_ELEMENT_TYPE; 
    }; 
    

var REACT_ELEMENT_TYPE = typeof Symbol === 'function' && Symbol['for'] && Symbol['for']('react.element') || 0xeac7; 

配列はオブジェクトであり、かつnullではありませんが、それは$$typeofプロパティがない持っていますここで設定されているため、チェックに失敗します。

$$typeofが設定されていません。なぜなら、Reactは、何かがリアクト要素かどうかを識別するために作成する要素にのみこのプロパティを追加するためです。これには、ネイティブなHTML要素が含まれ、データ型は含まれません。

したがって、ReactElement.isValidElementのチェックは失敗し、警告は表示されません。

+0

ありがとう!だから...バグだよね? –

+0

私はレポに問題をオープンしましたhttps://github.com/facebook/react/issues/9174 –

+0

私の理解では、はい! 'react-dom'からの' traverseAllChildrenImpl'関数は多次元配列内の子をトラバースする方法を知っています(再帰的に子ノードを構築するために自身を呼び出します)が、 'validateExplicitKey'関数はこれをしません – Anuj

1

私は最近同じことを考えていました。

私はhow the keys workについてReactJSの公式ドキュメントで理解した内容は、私は両方であるため、単にデータのフラット配列を持つものと同様、データのネストされた配列と同じ警告を受けることを期待するから、キー属性が設定されていないケースがあります。

キーヘルプ変更、追加、削除されたアイテムを特定します。要素は、配列内の要素に与えられ、要素に安定した同一性が与えられます。

私は実際にあなたが指摘同じケースを記述する、bug report (issue) in the ReactJS official GitHub repoで満たされたが、(ファンシー.map().reduce()鮫なし)に簡略化。

バグのように見えます。

PS:リアクションチームが私に反応するとすぐに私の回答を更新します。

関連する問題