ReactiveVar无法重新呈现React组件

时间:2016-08-11 21:40:23

标签: javascript meteor reactjs

我对流星中的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中,但我得到了相同的结果。 var被正确设置为true,因为autorun正确地记录了更改。

在另一个已复制此组件的组件中,我正确地重新呈现组件,但在.fetch()上使用findrenderTasks方法映射返回的数组它会呈现一个新组件列表。

我错过了什么?我怎么能解决它?

非常感谢!

1 个答案:

答案 0 :(得分: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,可以引用它来更新值。在这种情况下我们如何更新它?

最简单的方法是通过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。另一个是将回调函数传递给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 );
    ...
  }
  ...
};

这次比较好。

可以开发更多,但这实际上取决于您对您的应用程序的偏好。您和只有您才能做出设计决定。