在同一项目中使用mobx和redux-甚至在相同的组件/类中

时间:2018-11-11 22:24:16

标签: reactjs redux react-redux mobx mobx-react

首先要有一些背景知识

在学习过程中使用Typescript反应和还原。对于具有某种应用程序状态(而不是纯UI状态)的组件,我试图在react组件与基础逻辑和状态之间保持逻辑隔离。为此,对于以某种方式使用应用程序状态数据的组件,我实现了一个ViewModel类,该类在组件属性上设置,并包含封装该组件行为的属性和操作。因此,ViewModel将(例如)从后端获取数据,并将其呈现为react组件的属性。

实现这种分离的一个原因是要确保ViewModel可以独立于react组件中包含的纯粹与视图相关的方面进行单元测试。我认为对于最初的实现以及将来在将来的某些体系结构中需要重新实现逻辑而言,这都是很重要的-这样就可以理解并且自成体系,而无需对React,Redux或Mobx进行一系列的“布线”特定的体系结构。

我已经使用mobx(ViewModel中的@observable和@action装饰器,绑定到使用@observer装饰的组件)实现了这一点。到目前为止,我以这种方式实现的所有状态都位于组件内部,或者使用ViewModel层次结构传递给子组件。到目前为止,它的运行情况非常好,并且这种模式易于应用于新组件,并且对于熟悉淘汰赛的开发人员来说不会是一个巨大的飞跃。这对我当前的情况都是有利的。

但是,我现在希望使用全局存储的某种状态,以便可以在组件之间共享并持久化。我一直在研究使用redux存储。我真的很热衷于不要“用洗澡水把婴儿扔出去”,并希望继续将mobx用于“本地”应用程序状态,并出于先前概述的原因希望保持ViewModel分离。

到目前为止,我已经实现的方法是使用@observable装饰器像往常一样在ViewModel类中以@observable字段的形式创建redux状态属性。然后,我通过调用store.subscribe()订阅redux存储状态更改。当传递给订阅的回调触发时(使用mobx操作方法),我使用从状态检索的值设置了ViewModel上@observable字段的值。 Mobx非常聪明,仅在状态设置的值实际更改时才重新渲染。

当使用ViewModel的组件触发componentWillUnmount时,我调用unsubscribe()以避免不必要时保持大量订阅活动。

所以我的ViewModel类看起来像这样(这里只是大纲代码):

import { Unsubscribe } from "redux";

class ViewModel {
    @observable
    public fieldFromReduxState: string | null = null;

    private _unsubscribe: Unsubscribe | null = null;
    // Called by the containing component in componentDidMount
    public attach() {
        this._unsubscribe = store.subscribe(this._updateFromState);
        // Initial update from state
        this._updateFromState();
    }
    // Called by the containing component in componentWillUnmount
    public detach() {
        if (this._unsubscribe) {
            this._unsubscribe();
            this._unsubscribe = null;
        }
    }
    @action.bound
    private _updateFromState() {
        const state = store.getState();
        // Update local field from state
        this.fieldFromReduxState = state.myreducer.statevalue;
    }
}

和使用viewmodel的组件看起来像(再次,只是大纲代码):

interface IMyComponentProps {
    viewModel: ViewModel;
}

@observer
class MyView extends React.Component<IMyComponentProps> {

    public static defaultProps = {
        viewModel: new ViewModel()
    }

    public componentDidMount() {
        this.props.viewModel.attach();
    }

    public componentWillUnmount() {
        if (this.props.viewModel) {
            this.props.viewModel.detach();
        }
    }

    // In render, use this.props.viewModel.fieldName
    // Bind events to viewModel methods
    // In this way, the component retains just the pure view functionality
    //  and the ViewModel can be tested / re-used in isolation from react
    ...

}

我要寻找的是对那些对mobx,反应和还原经验更为丰富的人的见解/建议,它们是我可能会遇到此实现问题还是忽略了某些关键问题。我敏锐地意识到,这对我来说都是新事物,我可能会为自己制造一些令人讨厌的问题。我也将非常感兴趣,看看是否有人提出了将mobx与redux一起用于同一项目甚至组件中不同状态方案的良好模式。在我看来,这提供了两全其美的选择,可以选择国家应该居住的地方。

我知道将逻辑从组件移到单独的ViewModel类中的想法并不是每个人都喜欢的方法,因此,请允许我对此一点点幽默。

我也知道许多人会主张使用动作和化简器在redux中实现每个状态更改(包括从后端获取临时数据的结果),但是我真的不热衷于采用这种方式来使用组件不需要共享状态; mobx模型的操作是如此简单,特别是对于那些对redux概念没有太多经验的开发人员来说,他们的代码库正在从基因敲除js等较早的技术移植而来,或者对MVVM模式有了普遍的了解。

因此,总而言之,我主要是在寻找所描述的方法可能导致我陷入的陷阱和问题的任何指针,以及在可能的情况下如何解决这些问题的任何建议。

很抱歉,本文的长度,非常感谢您提供的任何帮助或建议。

0 个答案:

没有答案