【问题标题】:How should I access a service in a react-redux app我应该如何访问 react-redux 应用程序中的服务
【发布时间】:2017-06-16 01:49:18
【问题描述】:

我正在学习 React 和 Redux。我做了相当多的阅读并创建了一个基本的应用程序。我现在想创建一个简单的计算器应用程序作为更高级的培训练习。

计算器应用程序将非常基本,即。数字和操作按钮以及一个简单的文本字段,用于显示正在输入的数字或运行总数。它将模拟一个简单的桌面计算器。也就是说,如果您单击 5 按钮,文本字段中将出现一个 5。如果现在点击 6,显示变为 56。依次点击 +、3、1,现在显示显示 31。点击 =,将显示 87。

计算引擎(Calculator)的业务逻辑是一个服务,可以与应用程序本身分离。应用程序中应该只有一个计算器实例。我想知道的是如何使计算器可用于应用程序,尤其是。在减速器中。计算器需要保持一些状态,例如。到目前为止已经输入了哪些数字。

在 React-Redux 中,状态由单个对象表示,并通过 store 提供。计算器应该是一项状态吗? (另一个项目是要显示的当前值。)鉴于计算器永远不会改变,即。它总是指向相同的参考,这有意义吗? (计算器的内部状态会改变,但这对应用程序来说基本上是不可见的。)这是否意味着我的减速器将始终接受计算器作为状态并将其传回?我想我不想每次都复制一份。

或者通过某种 Singleton 使计算器可用更好?

或者还有其他更符合 React-Redux 习惯用法的方法吗?

【问题讨论】:

    标签: javascript react-native react-redux


    【解决方案1】:

    我想在 react/redux 中使用计算器之类的东西,我会在我的 reducer 中创建一个案例来处理按下的“=”按钮,当前值和表达式都通过操作对象传入。我会设想这样的减速器:

    const initialState = {
      totalValue: 0
    };
    
    export default function reducer(state = initialState, action = {}) {
      switch (action.type) {
        case EQUAL_PRESSED:
          // Do your work here to call your calculator service.
          // you can pass in action.currentTotal and action.expressionToEval
          // to whatever functions will do the actual work and return a new 
          // total.
          var newTotal = calcEngine(action.currentTotal, action.expressionToEval);
          return {
            ...state,
            totalValue: newTotal
          };
      }
    }
    
    export function equalPressed(currentTotal, expressionToEval) {
      return {
        type: EQUAL_PRESSED,
        currentTotal: currentTotal,
        expressionToEval: expressionToEval
      };
    }
    

    然后在我的 react 组件中,我将访问 redux 状态树并获取新的 totalValue 以显示在您显示结果的任何位置。

    【讨论】:

    • 几个问题:(a) 在您的示例中,我从哪里获取 calcEngine? (b) 我设想了计算器保持状态,例如。运行总数,历史记录等。这将允许我在其他地方重新使用它。这是一个坏主意吗?您似乎在建议所有这些状态都应该在商店中。谢谢。
    • @dave 我放在那里的 calcEngine 以显示被引用的服务来执行加/减/乘等的实际数学工作。您可以在减速器或动作中完成所有这些工作创建者 equalPressed() 但这很快就会变得混乱。
    • @dave 第二,在决定 state 应该在哪里时,我一直使用的经验法则是,如果它应该在组件卸载或页面刷新后幸存下来,它应该存在于 redux 中。我会说运行总数和历史都符合使用 redux 的条件。诸如“文件菜单是打开还是关闭”之类的内容不一定必须存在于 redux 中,并且可以在几乎没有人注意到的情况下轻松地在重新加载时重置为默认状态。
    • \@jiujitsucoder - 感谢您的回复。我知道状态存在于 redux 中(或由它管理)。我觉得 calc 引擎应该包含大部分内容,因为它应该理解它,而 UI/reducers 不应该。这似乎是您在代码中勾勒出来的内容。因此,如果我们将其放入服务中(正如我们俩似乎都认为的那样),我们如何管理对该服务的访问。它是商店的一部分吗?在您的代码中,您只需使用它。你是从哪里弄来的?谢谢。
    • @dave 是的,我将计算器视为一项单独的服务。我喜欢你设置的方式。我唯一要更改的另一部分是从计算器服务中取出运行总数并将其传入。它会为您的函数添加一个参数,但它会使整个计算器服务无状态,从而更容易测试。然而,这取决于你。这只是我的拙见。
    【解决方案2】:

    在进一步阅读了 Javascript (ES6) 中的 Singletons 并以 @jiujitsucoder 的回答为基础之后,我提出了自己的解决方案,似乎运行良好。

    Calculator 类作为单例提供给应用程序的其他组件。

    calculator.js

    class Calculator {
        constructor() {
            this.runningTotal = 0;
        }
        currentValue() {
            return this.runningTotal;
        }
        operation() { ... }
        ...
        }
    }
    
    let instance = new Calculator();
    export default instance
    

    reducer(例如)接收与 UI 中的按键对应的操作,并相应地指示计算器。

    reducer.js

    import Calculator from './calculator';
    const initialValue = 0;
    export default function(state = initialValue, action) {
        switch (action.type) {
            case PROCESS_DIGIT:
                Calculator.digit(action.digit);
                return Calculator.currentValue();
            case PROCESS_OPERATOR:
                Calculator.operator(action.operator);
                return Calculator.currentValue();
            }
        return state;
    }
    

    【讨论】:

      猜你喜欢
      • 2016-08-06
      • 2016-06-10
      • 2022-11-02
      • 1970-01-01
      • 2020-10-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-05-03
      相关资源
      最近更新 更多