当在测试中更新可观察值时,mobx计算函数不会重新运行

时间:2018-02-19 22:58:24

标签: javascript reactjs mocha enzyme mobx

我正在尝试为基于mobx的反应编写单元测试。出于某种原因,当<script> $( function() { $( "#divID" ).resizable(); } ); </script>` 中的@observable值更新时,@action函数不会像您期望的那样重新运行。

代码:

商品

@computed

COMPONENT 1

class NameStore {
    @observable name;

    @action setName(name) {
        this.name = name;
    }
}

COMPONENT 2

@observer
class Name {
    @computed get name() {
        if (this.props.nameStore.name) {
            return `${this.props.nameStore.name} is awesome!`;
        }

        return null;
    }

    render() {
        return (
            <div className="name">
                {this.name}
            </div>
        );
    }
}

TEST

@observer
class Name {
    setName() {
        this.props.nameStore.setName(this.name);
    }

    render() {
        return (
            <form onSubmit={this.setName.bind(this)}>
                <input type="text" ref={input => this.name = input} />
            </form>
        );
    }
}

出于某种原因,在测试中,define('Name component', () => { let markup; beforeEach(() => { const nameStore = new NameStore(); markup = mount( <div> <Component1 nameStore={nameStore} /> <Component2 nameStore={nameStore} /> </div> ); }); it('should re-render name when updated', (done) => { expect(markup.find('.name').text()).to.be.blank; markup.find('form input').first().value = "john"; markup.find('form').simulate('submit'); expect(markup.find('.name').text()).to.equal("john is awesome") }); }); {this.name}的实际值保持不变,即使我能够验证商店中的Component1函数是否被调用正确并具有正确的价值。

关于为什么setName不重新渲染的任何帮助都将非常感激。

此外,这是一个人为的例子,因为实际的例子是专有的..如果这个例子感到愚蠢,请原谅我:)

谢谢!

1 个答案:

答案 0 :(得分:1)

错误很少:

  • 两个组件均未延伸React.Component
  • @computed应该在商店
  • input应绑定到onChange并更新其value
  • 浏览器可能会抱怨input值未定义。最好将其设置为空字符串。
  • input值位于event.target.valueref={input => this.name = input}会将this.name分配给html组件。
  • 处理表单时的经验法则是致电event.preventDefault()

以下代码是基于您的代码的完整工作示例:

import React from 'react';
import { observable, action, computed } from 'mobx';
import { observer } from 'mobx-react';

class NameStore {
  @observable name = '';

  @action
  setName = name => {
    this.name = name;
  }

  @computed
  get awesomeName() {
    return this.name ? `${this.name} is awesome!` : '';
  }
}

@observer
class NameField extends React.Component {
  render() {
    const { nameStore } = this.props;
    return <div className="name"> {nameStore.awesomeName} </div>;
  }
}

@observer
class NameInput extends React.Component {
  render() {
    const { nameStore } = this.props;
    return (
      <form>
        <input
          type="text"
          onChange={this.onChange}
          value={nameStore.name}
        />
      </form>
    );
  }

  onChange = e => {
    const { nameStore } = this.props;
    nameStore.setName(e.target.value);
    e.preventDefault();
  }
}

@observer
class App extends React.Component {
  nameStore = new NameStore();

  render() {
    return (
      <div>
        <NameField nameStore={this.nameStore} />
        <NameInput nameStore={this.nameStore} />
      </div>
    );
  }
}

export default App;

额外注意:由于使用了箭头功能,我不必致电.bind(this)