2016-04-20 16 views
1

私はReactの「ステートレスな子、ステートフルな親」のイデオロギーに従うようにしています。ここ動的に作成された子コンポーネントが新しい小道具を受け取っていない

私の苦境を示して自分のコード(のCoffeeScript + JSX)の簡易版であるこの例では

@FormBlock = React.createClass 
    getInitialState: -> 
    fields: [], editMode: false 

    toggle: -> 
    @setState editMode: [email protected] 

    addChild: -> 
    child = `<EditableText key={Date.now()} text="FAILS" editMode={this.state.editMode}/>` 
    items = @state.fields.concat child 
    @setState fields: items 

    render: -> 
    `<div> 
     <a onClick={this.toggle}>Change Mode</a><br/> 
     <a onClick={this.addChild}>Add Child</a><br/> 
     <EditableText text="WORKS" editMode={this.state.editMode}/><br/> 
     {this.state.fields} 
    </div>` 


@EditableText = React.createClass 
    render: -> 
    if @props.editMode 
     `<input className="editable" defaultValue={this.props.text}/>` 
    else 
     `<span className="editable">{this.props.text}</span>` 

、成分<FormBlock>は最初fieldsそのeditMode=false全く含まないであろう。 Change Modeボタンをクリックしてをtrueに変更すると、<EditableText>コンポーネントの内容は<span>から<input>に変更され、ユーザーが変更できるようになります。

<FormBlock>renderメソッド(つまり<EditableText text="WORKS".../>)に含まれるダミーコンポーネントは完全に機能しますが、これは子供にとっては機能しません。私は作成時にタイプ<EditableText>のすべての子どもがその最初のpropsを受け取ることをテストしましたが、state.editModeが変更されたとき、すべての子どもは変更されません(私はcomponentWillReceivePropsが子どもに対して発射しないことを確認しました。 )。

私はこの問題を解決しようとしています。助けてください!!!

答えて

2

問題は、EditableTextを呼び出した結果がコンポーネントの状態で保存されていることです。つまり、子供がまだされていない(答えを

@FormBlock = React.createClass 
 
    getInitialState: -> 
 
    fields: [], editMode: false 
 

 
    toggle: -> 
 
    @setState editMode: [email protected] 
 

 
    addChild: -> 
 
    items = @state.fields.concat {} 
 
    @setState fields: items 
 

 
    render: -> 
 
    `<div> 
 
     <a onClick={this.toggle}>Change Mode</a><br/> 
 
     <a onClick={this.addChild}>Add Child</a><br/> 
 
     <EditableText text="WORKS" editMode={this.state.editMode}/><br/> 
 
     { this.state.fields.map @renderChild } 
 
    </div>` 
 

 
    renderChild: -> 
 
     `<EditableText 
 
      key={Date.now()} 
 
      text="FAILS" 
 
      editMode={this.state.editMode}/>`

+0

おかげで、これは動作しません:あなたは動的状態に基づいて、子コンポーネントをレンダリングしたい場合は、代わりにrenderメソッドで行います親が更新されたときに更新されます)。あなたのバージョンの 'addChild'は新しい子をリストに追加しません。親のレンダリングメソッドで子をレンダリングするというあなたの提案については、私のコードスニペット '{this.state.fields}'はすでにこれを行っています。 'map'メソッドを使うのは本質的に同じですが、もっと冗長です。 – Vadim

+0

あなたは部分的に正しいです。あなたのアプローチと上記の説明との大きな違いは、親のrenderメソッドが呼び出されたときに子コンポーネントが再レンダリングされるのに対し、子コンポーネントのrenderメソッドが呼び出された結果が親の状態であり、単にレンダリングされる代わりに呼び出されるだけである。 – Niko

+0

私の例がうまくいかない理由は、現在のタイムスタンプをキーとして使用しているからです。 renderChildメソッドを呼び出すには、数ミリ秒の時間がかかります。このように、提供されるタイムスタンプはすべてのeditableTextインスタンスで同じであり、Reactのリコンシリエーションアルゴリズムはすべての要素を重複キーでフィルタリングし、EditableTextコンポーネントのインスタンスを1つだけ残します。実際の例が見つかりました[ここ](https://jsfiddle.net/1eur6xkd/) – Niko

関連する問題