2016-08-11 14 views
0

React in Meteorではかなり新しいです。ReactVarは再レンダリングされないReactコンポーネント

TL:DR:私のデータコンテナで、私のReactiveVarの値を変更しても私のビューは再レンダリングされません。

私はこのコードを持っている:

import React, { Component, PropTypes } from 'react'; 
import ReactDOM from 'react-dom'; 
import { Meteor } from 'meteor/meteor'; 
import { createContainer } from 'meteor/react-meteor-data'; 

// Mail composer - interface for generating enews 
class MailComposer extends Component { 
    constructor(props) { 
    super(props); 
    } 

    handleSubmit(event) { 
    event.preventDefault(); 

    const text = this.refs.mailText.value.trim(), 
      title = this.refs.mailTitle.value.trim(), 
      rcpts = this.refs.mailRecpts.value.trim(); 

    console.log(text, title, rcpts); 

    if (text && title && rcpts) { 
     // ... 
     this.props.hasTestedIt.set(true); 
    } else { 
     // ... 
    } 
    } 

    componentDidMount() { 
    console.log(this); 
    $(this.refs.textArea).autosize(); 
    } 

    getBtnText() { 
    return (this.props.hasTestedIt.get() ? "Send it" : "Test it"); 
    } 

    render() { 
    let self = this; 
    Tracker.autorun(function(){ 
     console.log(self.props.hasTestedIt.get()); 
    }); 

    return (
     <div className="panel panel-default panel-primary"> 
     <div className="panel-heading"> 
      <h3 className="panel-title">Mail composer</h3> 
     </div> 
     <div className="panel-body"> 
      <form className="form-group" onSubmit={this.handleSubmit.bind(this)}> 
      <div className="input-group"> 
       <span className="input-group-addon" id="basic-addon1">Title</span> 
       <input type="text" className="form-control" ref="mailTitle" /> 
      </div> 
      <br/> 
      <label htmlFor="js-recipients">Recipients:</label> 
      <select className="form-control" width="width: initial;" id="js-recipients" ref="mailRecpts"> 
       <option>Admins</option> 
       <option>All</option> 
      </select> 
      <br/> 
      <label htmlFor="comment">Text:</label> 
      <textarea className="form-control" rows="5" ref="mailText"></textarea> 
      <br/> 
      <button className="btn btn-primary" type="submit"> 
       {this.getBtnText()} 
      </button> 
      </form> 
     </div> 
     </div> 
    ); 
    } 
} 

MailComposer.propTypes = { 
    hasTestedIt: PropTypes.object.isRequired 
}; 

export default createContainer(() => { 
    return { 
    hasTestedIt: new ReactiveVar(false) 
    }; 
}, MailComposer);` 

をしかし、私は私の提出ハンドラで私ReactiveVar小道具を設定すると、ボタンにgetBtnTextメソッドによって返されるテキストは変更されません。私は、HTML内に直接三項を入れようとしましたが、私は同じ結果を得ました。 autorunが正しく変更を記録するので、varは正しくtrueに設定されます。この1つは、コピーされた別のコンポーネントでは、

、私は正しくコンポーネントを再描画しますが、新しいコンポーネントのリストをレンダリングrenderTasks方法で返された配列をマッピングするためにfind.fetch()を使用してください。

どうしたらいいですか?そして私はそれをどうやって修正することができますか

ありがとうございます!

答えて

2

渡されたhasTestedIt小道具自体が変更されていないため、コンポーネントが更新されません。これは、それが保持している価値です。

あなたが実際に興味を持っている価値を見てください。

// Declare the reactive source somewhere appropriately. 
const hasTestedIt = new ReactiveVar(false); 

// Watch its value instead. 
export default createContainer(() => { 
    return { 
    hasTestedIt: hasTestedIt.get() 
    }; 
}, MailComposer);` 

それが今MailComposerに渡された値であることに注意してください、ないもう値を更新するために参照することができますReactiveVar。この場合、どうすれば更新できますか?

最も簡単なアプローチの1つはhasTestedItと同様ですが、これは私の個人的な推奨事項ではありません。

// Watch its value instead. 
export default createContainer(() => { 
    return { 
    // Reactive source that triggers re-rendering. 
    valueOfHasTestedIt: hasTestedIt.get(), 
    // Provided for the contained component to reference to set new values. 
    // Leaving this alone doesn't trigger re-rendering! 
    hasTested 
    }; 
}, MailComposer); 

IMOはエレガントではありません。もう1つは、値を更新するために使用できるMailComposerにコールバック関数を渡すことです。

const updateHasTestedIt = (value) => hasTestedIt.set(value); 

// Watch its value instead. 
export default createContainer(() => { 
    return { 
    hasTestedIt: hasTestedIt.get(), 
    updateHasTestedIt, 
    }; 
}, MailComposer); 

class MailComposer extends Component { 
    ... 
    handleSubmit(event) { 
    ... 
    this.props.updateHasTestedIt(true); 
    ... 
    } 
    ... 
}; 

今回はよかったです。

もっと発展させることは可能ですが、あなたのアプリケーションの好みによります。あなたとあなただけが意思決定を下すことができます。

+0

'hasTestedIt'も前と同じように渡すと、コンテナに直接値を渡すことを意味しますか?もしそうなら、値を変更することは、それがreactiveVarからではないにもかかわらず再レンダリングを開始する可能性がありますか? 多くのご協力をいただき、ありがとうございます。 –

+1

@David Panart、はい。 'createContainer'の戻り値が浅い比較で変更されなければ、' hasTestedIt'が反応するソースであるにもかかわらず、再レンダリングはトリガーされません。 – Season

関連する問題