2016-03-21 23 views
0

私は、任意の量のサブコンポーネントを追跡しようとしています。React:動的コンポーネントの参照の作成と参照

通常はthis.refs.refNameを参照するだけですが、私の場合、私は追跡する必要がある任意の量の参照を持っています。私は間違って私に知らせて問題にアプローチしていた場合

var NamesList = React.createClass({ 
    getAllNames: function() { 
    // Somehow return an array of names... 

    var names = []; 
    this.refs.????.forEach(function (span) { 
     names.push(span.textContent); 
    }) 
    }, 

    render: function() { 
    var names = ['jack','fred','bob','carl']; 
    var spans = []; 

    names.forEach(function (name) { 
     spans.push(<span contentEditable={true} ref='?????'>name</span>); 
    }); 

    return (
     <div> 
     {spans} 
     </div>; 
    ); 
    } 
}); 

ReactDOM.render(<NamesList></NamesList>, mountNode); 

:ここ

は簡潔な例です。私の望む結果は、RESTfulなサービスからReactコンポーネントにデータを渡し、ユーザーがそのデータを編集できるようにし、必要に応じて再度エクスポートすることです。 React refs docsでこれに対する答えを見つけることができませんでした。

答えて

1

次配列の内の各スパンにREFを保持は、各スパンがaddSpanRef方法を使用して参考文献アレイに自身を追加するため、この作品this.spans

と呼ばれます。

getAllNamesは、すべてのスパンを参照し、textContentを取得します。

(スパンではなく)サブコンポーネントがある場合、それらの子ノードでメソッドを呼び出すことができます。

var NamesList = React.createClass({ 

    // returns an array of names 
    getAllNames() { 
    return this.spans.map((span) => span.textContent); 
    }, 

    // Add to our spans refs array 
    addSpanRef (node) { 
    this.spans = [...this.spans, node]; 
    }, 

    render: function() { 
    this.spans = []; // create the spans refs array 
    var names = ['jack','fred','bob','carl']; 

    // Save a ref to "this" for the forEach loop 
    var thisRef = this; 
    names.forEach(function (name) { 
     spans.push(<span contentEditable={true} ref={thisRef.addSpanRef}>name</span>); 
    }); 

    return (
     <div> 
     {spans} 
     </div>; 
    ); 
    } 
}); 

ReactDOM.render(<NamesList></NamesList>, mountNode); 
1

1.迅速かつ汚いソリューション:すべての名前を読むためにコンテナコンポーネントにREFを通じて名前を読む

一つの方法は、容器上にREFを入れて、childNodeがスパン上のTextContentを読むことです。

componentDidMount: function() { 
    var elem = this.refs.container.getDOMNode(); 
    var nameNodes = elem.children; 
    var names = []; 
    for (var i=0; i<nameNodes.length; i++) { 
     names.push(nameNodes[i].textContent); 
    } 
    console.log(names); 
    }, 

Working codepen of this hereがあります。

警告::上記のコードは汚れています。ユーザーはDOMの変更を知らずにスパンの内容を変更できます。そしてそれは(非常に)悪い考えです。ソリューション

2.クリーナーだから、状態が必要になります。ユーザーは、スパンの内容を変更し、それについて知っているニーズを反応させることができます。
すべての(新しい)編集された名前の配列も必要なので、この状態はコンテナレベルに存在する必要があります。
純粋な<EditableSpan>コンポーネントを持つソリューションがあります。これは、名前が変更されるたびに親クラスのメソッドを呼び出します。

var EditableSpan = React.createClass({ 
    onChange: function() { 
    var newContent = event.target.textContent; 
    this.props.onChange(this.props.index, newContent); 
    }, 
    render: function() { 
    return <span 
      contentEditable={true} 
      onInput={this.onChange}> 
     {this.props.name}</span> 
    } 
}); 

彼らを必要としないので、このクリーナーソリューションは、もはや、レフリーを使用しないことに注意してください:DOMからの読み取りに参照文献を必要としないすべてのデータが反応することが知られているので、反応します。代わりに、すべての変更時にevent.targetが読み込まれ、コンテナの状態が更新されます。

ここにはfull working codepenがあります。

警告:このソリューションでは、迅速かつ汚れたkeys(名前)を追加しました。 Reactは、一意の(そして索引ではない)キーを必要とします。リスト内の名前は一意であることが保証されていないため、これを行うにはもっとスマートな解決策が必要です(IDまたはタイムスタンプの作成が必要)。

+0

申し訳ありませんが、私はスパンの名前を動的に取得しようとしています。あなたが行った変更は、_setting_ spanについてのものであるように見えます。疑似コードの場合:各スパンについて、textContentを取得し、配列として返します。それが私が求めていることを説明するのに役立つのですか? – joshuakcockrell

+0

答えを2つのソリューションで更新しました。 2番目の解決策はスパンのtextContentを持つ配列を返しますが、refは使用しません。 ReactはtextContentの唯一の所有者でマネージャでなければなりません。したがって、名前を取得するためにrefを使用する必要はありません(また、バグ/管理不能なコードのソース)。 – wintvelt