admin管理员组文章数量:1431413
I am attempting to write a unit test for mobx-based reaction. For some reason, when the @observable
value is updated in an @action
, the @puted
function does not re-run as you'd expect.
Code:
STORE
class NameStore {
@observable name;
@action setName(name) {
this.name = name;
}
}
COMPONENT 1
@observer
class Name {
@puted get name() {
if (this.props.nameStore.name) {
return `${this.props.nameStore.name} is awesome!`;
}
return null;
}
render() {
return (
<div className="name">
{this.name}
</div>
);
}
}
COMPONENT 2
@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>
);
}
}
TEST
define('Name ponent', () => {
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")
});
});
For some reason, in the test, the actual value of {this.name}
in Component1
remains unchanged even though I'm able to verify that the setName
function in the store is being called properly and with the correct value.
Any help as to why Component1
is not re-rendering would be much appreciated.
Also, this is a contrived example as the actual example is proprietary..so forgive me if this example feels dumb :)
Thanks!
I am attempting to write a unit test for mobx-based reaction. For some reason, when the @observable
value is updated in an @action
, the @puted
function does not re-run as you'd expect.
Code:
STORE
class NameStore {
@observable name;
@action setName(name) {
this.name = name;
}
}
COMPONENT 1
@observer
class Name {
@puted get name() {
if (this.props.nameStore.name) {
return `${this.props.nameStore.name} is awesome!`;
}
return null;
}
render() {
return (
<div className="name">
{this.name}
</div>
);
}
}
COMPONENT 2
@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>
);
}
}
TEST
define('Name ponent', () => {
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")
});
});
For some reason, in the test, the actual value of {this.name}
in Component1
remains unchanged even though I'm able to verify that the setName
function in the store is being called properly and with the correct value.
Any help as to why Component1
is not re-rendering would be much appreciated.
Also, this is a contrived example as the actual example is proprietary..so forgive me if this example feels dumb :)
Thanks!
Share Improve this question asked Feb 19, 2018 at 22:58 MarkMark 11.1k6 gold badges34 silver badges48 bronze badges1 Answer
Reset to default 4There are few mistakes:
- Neither of the ponents extends
React.Component
@puted
should be in the storeinput
should bind toonChange
and updates itsvalue
- Browser may plain
input
value is undefined. It's better to set it to empty string. input
value is inevent.target.value
,ref={input => this.name = input}
will assignthis.name
to the html ponent.- The rule of thumb when deal with form is to call
event.preventDefault()
The code below is a pleted working example based on your code:
import React from 'react';
import { observable, action, puted } from 'mobx';
import { observer } from 'mobx-react';
class NameStore {
@observable name = '';
@action
setName = name => {
this.name = name;
}
@puted
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;
Extra note: Since the arrow function has been used, I don't have to call .bind(this)
.
版权声明:本文标题:javascript - mobx computed function not re-running when observable value is updated in test - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1745488489a2660494.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论