从 redux 存储中获取数据到简单函数的最佳实践方法是什么?

What is the best practice approach to getting data from the redux store into a simple function?

假设我有一个名为 calculateFees 的函数,它需要从后端发送一些数据,例如 consultingFee。它看起来像:

const calculateFees = itemPrice => itemPrice * [consultingFee]

[consultingFee] 是一个占位符,因为我不确定如何从 redux 商店获取它。我们还假设 calculateFees 要复杂得多,它有大约 10 多种费用,并且被几十个组件使用。我能想到的选项是:

1) 传入调用它的连接到 redux 状态的 class 的所有费用。

(例如 calculateFees(itemPrice, feeOne, feeTwo, FeeThree, ...)

2) 复制每个连接到 redux 状态的 class 中的代码。

3) 导出整个商店(或其中的一部分),以便 calculateFees 函数可以通过导入访问数据。

4) 不确定这是否可能,但是使用静态方法创建一个 class,并将其连接到 redux 存储。然后使用它,例如 MyCompanyFees.calculateFees.

5) 创建一个仅从状态中提取数据的 thunk,以及 returns 计算的费用。使用它似乎不正确,因为它不是异步的,也不会更新状态树。

我想获得一些关于最佳实践方法的指导/建议,因为我不喜欢 1、2 或 3。

一个简单的 calculation/utility 函数不应该知道它的数据来自哪里,应该只接受它作为参数:

const calculateFees = (itemPrice, consultingFee) => itemPrice * consultingFee

如果数据来自商店,那么 calculateFees 应该在选择器中调用。

选择器:

const getCalculatedFees = (state, { itemId }) => {
    const itemPrice = state.items[itemId].price;
    const consultingFee = state.consultingFee;

    return calculateFees(itemPrice, consultingFee);
}

然后选择器可以被组件或与动作相关的函数使用,例如 thunks 和 sagas。

组件:

connect(
    state => ({
        calculatedFees: getCalculatedFees(state)
    })
)(MyComponent)

砰砰声:

const myAction = itemId => (dispatch, getState) => {
    const calculatedFee = getCalculatedFees(getState(), { itemId });

    // do stuff...
    dispatch(doSomethingElse(calculatedFee));
}

传奇:

function* mySaga({ itemId }) {
    const calculatedFee = yield select(getCalculatedFees, { itemId });

    // ...
}

我想说这在很大程度上取决于特定的用例,比如这些值(意味着计算函数的输入)可以改变的频率(是购物车之类的东西还是更像是生成的报告之类的东西)事情,当你获取一次数据时就是这样)并且如果它只是每个视图的一个计算或多个具有不同输入的计算(例如你必须计算 table 中每一行的费用)。

首先,计算应该是一个单独的函数,它获取它需要的所有数据作为参数(这样你也可以很容易地对它进行单元测试)并且不关心它是否在 React 应用程序中使用或者你是否重新使用 Redux 或其他任何东西。如果您认为它将使用相同的参数多次调用,您还可以阅读称为记忆的概念,但我想在大多数情况下,记忆应该发生在这个函数之外。

现在,假设您的商店中已有其余数据(您提到的 consultingFee 占位符),并且希望在收到后端响应后计算出值。在这种情况下,您可以从存储中提取值,如 bsapaka 的答案所示,并将计算出的值放入 redux 存储中,您可以在需要的地方访问。如果您发出一次请求,显示计算值就足够了,仅此而已,您知道如果您需要再次计算它,您将有不同的输入值并且必须再次调用后端并且您不需要缓存结果,尽管我认为如果是这种情况,您根本不应该将计算出的值存储在您的商店中。

您还可以在 mapStateToProps 函数中进一步使用选择器,reselect 库对此很有用(请务必阅读 README 的 "Sharing Selectors with Props Across Multiple Component Instances" 部分)。这样,您就拥有了分派操作的组件,该操作从后端获取您需要的数据并将其放入 redux 存储中。在 mapStateToProps 中,您使用 memoized 选择器收集它需要的所有数据并计算结果,除非输入(在这种情况下来自 redux 存储的相关值)发生变化,否则不会重新计算。我更喜欢这种方法,因为它减少了 redux 中的副作用,并且对我来说更具声明性,但我也更喜欢将 redux 用作具有原始值的缓存,如果我需要从中派生值,我会使用 memoized 选择器。