【问题标题】:MobX local state vs global stateMobX 本地状态与全局状态
【发布时间】:2019-09-29 02:08:34
【问题描述】:

我正在使用 React 和 mobx 来处理应用程序状态。

我正在使用通过外部存储(ajax 调用、过滤器或映射数组等)更改数据的转储组件

在表单中,当您必须通过 onChange 事件处理输入更改时,目前我在组件本身内部使用 observable 和 action。

这是一种不好的做法吗?或者我应该把所有的动作和可观察的数据放在一个外部状态中?

如果相反,这种做法是可以接受的,我该如何解决我必须重置本地可观察状态(如文本输入)以响应在外部存储中执行的 ajax 调用操作的情况? 我可以在动作存储中使用回调来放弃对组件内部动作的控制,如下例所示:

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()
  })
 }
}

还有其他处理类似情况的最佳做法吗?

【问题讨论】:

    标签: javascript reactjs state mobx


    【解决方案1】:

    这个答案是不正确的,即使是 Mobx。阅读下面的链接以获取更多信息。请参阅“@observer 组件”下的文档。

    https://mobx.js.org/refguide/observer-component.html

    下面的文字也被复制了:

    可观察的本地组件状态

    就像普通类一样,您可以使用 @observable 装饰器在组件上引入可观察属性。这意味着您可以在不需要由 React 的冗长和命令式 setState 机制管理的组件中拥有本地状态,但同样强大。反应状态将被渲染获取,但不会显式调用除 componentWillUpdate 和 componentDidUpdate 之外的其他 React 生命周期方法。如果您需要其他 React 生命周期方法,只需使用普通的基于 React 状态的 API。

    上面的例子也可以写成:

    import { observer } from "mobx-react"
    import { observable } from "mobx"
    
    @observer
    class Timer extends React.Component {
      @observable secondsPassed = 0
    
      componentWillMount() {
        setInterval(() => {
          this.secondsPassed++
        }, 1000)
      }
    
      render() {
        return <span>Seconds passed: {this.secondsPassed} </span>
      }
    }
    
    ReactDOM.render(<Timer />, document.body)
    

    ...基于钩子的组件中可观察到的本地状态 要在函数组件中处理本地可观察状态,可以使用 useLocalStore 和 useAsObservableSource 挂钩。

    【讨论】:

      【解决方案2】:

      我认为一般的答案是 MobX(或就此而言的 Redux)不是表单状态的正确位置。这有很多原因,但主要是出于性能、复杂性和可维护性的考虑。 MobX/Redux 用于全局应用程序状态,而表单状态更本地化。

      社区正在转向像 Formik 这样的库,它可以让您在组件内本地完全管理表单状态和生命周期。它也适用于 MobX/Redux,可选择从全局状态初始化值。看看吧,很不错!

      https://github.com/jaredpalmer/formik

      【讨论】:

      • 感谢@JedRichards 的回复。我已经查看了 formik 库,但我认为并不能完全解决我的疑问。没关系,我可以使用一些第三方库管理本地状态或在组件内部管理我自己,但是我必须将 ajax 调用放在组件内部(或者可能调用外部存储操作并通过回调放弃对组件的控制)。对吗?
      • 是的,您必须决定我们要将您的 ajax 调用放在哪里。如果你愿意,你可以继续在你的 MobX 服务上保留它,如果这有意义的话......使用像 Formik 这样的库并不能阻止它。
      猜你喜欢
      • 1970-01-01
      • 2018-05-02
      • 2020-08-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多