I'm using React with mobx to handle application state.
I'm using dump ponents which alter data through the external store (ajax call, filter or map array etc ...)
Instead in forms, when you have to handle input change through onChange event, currently I'm using observable and action inside the ponent itself.
Is it a bad practice? Or should I put all the actions and observable data inside an external state?
If instead, this practice is acceptable, how can I address the case in which I have to reset a local observable state (like text input) in reaction to ajax call action executed in an external store? Could i use callback in action store to give up the control to an action inside the ponent, like in the following example:
import React from 'react';
import { observer, inject } from "mobx-react";
import { observable, action } from "mobx";
@inject("rootStore")
@observer
class ContactForm extends React.Component {
constructor(props) {
super(props);
this.externaStore = this.props.rootStore.contactStore
this.onChangeInput = this.onChangeInput.bind(this)
}
@observable text = ''
@action
onChangeInput(event) {
this.text = event.target.value
}
@action
resetForm() {
this.text = ''
}
render() {
return (
<form>
<div className="form-group">
<label htmlFor="input-text" className="control-label">Text input:
</label>
<input onChange={this.onChangeInput} type="text" value={this.text} id="input-text" name="input-text" className="form-control" />
</div>
<button onClick={() => this.externaStore.submitForm(this.text, this.resetForm)} className="btn btn-danger btn-xs" type="button" title="Aggiungi">
<i className="fa fa-save"></i> Aggiungi
</button>
</form>
)
}
}
class ExternalStore {
constructor(rootStore) {
this.rootStore = rootStore
this.service = rootStore.service
}
@observable textList = []
@action
submitForm(text, cb) {
this.service.doAjax('POST', '/api/text', JSON.stringify(text)).then(data => {
this.textList.push(text)
cb()
})
}
}
Are there another best practice to handle similar cases?
I'm using React with mobx to handle application state.
I'm using dump ponents which alter data through the external store (ajax call, filter or map array etc ...)
Instead in forms, when you have to handle input change through onChange event, currently I'm using observable and action inside the ponent itself.
Is it a bad practice? Or should I put all the actions and observable data inside an external state?
If instead, this practice is acceptable, how can I address the case in which I have to reset a local observable state (like text input) in reaction to ajax call action executed in an external store? Could i use callback in action store to give up the control to an action inside the ponent, like in the following example:
import React from 'react';
import { observer, inject } from "mobx-react";
import { observable, action } from "mobx";
@inject("rootStore")
@observer
class ContactForm extends React.Component {
constructor(props) {
super(props);
this.externaStore = this.props.rootStore.contactStore
this.onChangeInput = this.onChangeInput.bind(this)
}
@observable text = ''
@action
onChangeInput(event) {
this.text = event.target.value
}
@action
resetForm() {
this.text = ''
}
render() {
return (
<form>
<div className="form-group">
<label htmlFor="input-text" className="control-label">Text input:
</label>
<input onChange={this.onChangeInput} type="text" value={this.text} id="input-text" name="input-text" className="form-control" />
</div>
<button onClick={() => this.externaStore.submitForm(this.text, this.resetForm)} className="btn btn-danger btn-xs" type="button" title="Aggiungi">
<i className="fa fa-save"></i> Aggiungi
</button>
</form>
)
}
}
class ExternalStore {
constructor(rootStore) {
this.rootStore = rootStore
this.service = rootStore.service
}
@observable textList = []
@action
submitForm(text, cb) {
this.service.doAjax('POST', '/api/text', JSON.stringify(text)).then(data => {
this.textList.push(text)
cb()
})
}
}
Are there another best practice to handle similar cases?
Share Improve this question edited Dec 14, 2018 at 9:44 mancioshell asked Dec 14, 2018 at 9:16 mancioshellmancioshell 372 silver badges10 bronze badges2 Answers
Reset to default 4This answer is not correct, even with Mobx. Read the link below for more information. See the documentation under the "@observer ponent".
https://mobx.js/refguide/observer-ponent.html
The text is copied below as well:
Observable local ponent state
Just like normal classes, you can introduce observable properties on a ponent by using the @observable decorator. This means that you can have local state in ponents that doesn't need to be managed by React's verbose and imperative setState mechanism, but is as powerful. The reactive state will be picked up by render but will not explicitly invoke other React lifecycle methods except ponentWillUpdate and ponentDidUpdate. If you need other React lifecycle methods, just use the normal React state based APIs.
The example above could also have been written as:
import { observer } from "mobx-react"
import { observable } from "mobx"
@observer
class Timer extends React.Component {
@observable secondsPassed = 0
ponentWillMount() {
setInterval(() => {
this.secondsPassed++
}, 1000)
}
render() {
return <span>Seconds passed: {this.secondsPassed} </span>
}
}
ReactDOM.render(<Timer />, document.body)
...Observable local state in hook based ponents To work with local observable state inside function ponents, the useLocalStore and useAsObservableSource hooks can be used.
I think the general answer is that MobX (or Redux for that matter) isn't the right place for form state. This is for many reasons, but mainly for performance, plexity and maintainability concerns. MobX/Redux is for global application state, whereas form state is much more local.
The munity is moving towards libraries like Formik, that let you fully manage the form state and lifecycle locally within the ponent. It works well with MobX/Redux too, to optionally initialise the values from global state. Check it out, it's pretty great!
https://github./jaredpalmer/formik