【问题标题】:Redux Store & third party data structuresRedux Store 和第三方数据结构
【发布时间】:2016-01-07 13:06:41
【问题描述】:

这是一个关于将 redux 与 3rd 方库混合的问题。我很清楚这与 Redux 指南相反。主要是为了讨论和探索——我也不想污染他们的 Github 问题;)

第三方数据 我们使用关系和不可变数据结构模块来存储我们的应用程序数据。简而言之,该模块的工作方式有点像关系数据库:

  • 它公开了表格
  • 表格包含应用程序数据
  • 表有 4 种方法:get、post、put、delete
  • 数据对象通过索引/主键动态地相互引用

当前的 Redux 存储结构 由于我们使用的是 Redux,我们最初选择不直接公开表,因为它们包含方法。我们改为公开Table.get(); 的结果,它返回它的数据对象数组。

因此,我们的 reducer 通过使用 3rd 方模块来“更新状态”。重载由第 3 方完成,减速机基本总是返回Table.get();。 我们的商店看起来像这样:

// the application data (built by relational-json)
var appDB = {
    People: {
        get: function() {},
        post: function() {},
        put: function() {},
        delete: function() {}
    },
    Organization: {
        get: function() {},
        post: function() {},
        put: function() {},
        delete: function() {}
    },
    Address: {
        get: function() {},
        post: function() {},
        put: function() {},
        delete: function() {}
    }
};

// example Reducer
store = createStore(combineReducers({
    Person: function personReducer(state, action) {
        "use strict";

        switch (action.type) {
            case "UPDATE_PERSON_LIST":
            case "UPDATE_PERSON": {
                appDB.Person.put(action.data, "Person");

                return appDB.Person.get();
            }

            case "CREATE_PERSON": {
                appDB.Person.post(action.data, "Person");

                return appDB.Person.get();
            }

            default: {
                return appDB.Person.get();
            }
        }
    },
    Organization: function personReducer(state, action) {
        "use strict";

        switch (action.type) {
            case "UPDATE_ADDRESS_LIST":
            case "UPDATE_ADDRESS": {
                appDB.Organization.put(action.data, "Organization");

                return appDB.Organization.get();
            }

            case "CREATE_ADDRESS": {
                appDB.Organization.post(action.data, "Organization");

                return appDB.Organization.get();
            }

            default: {
                return appDB.Organization.get();
            }
        }
    },
    Address: function personReducer(state, action) {
        "use strict";

        switch (action.type) {
            case "UPDATE_ADDRESS_LIST":
            case "UPDATE_ADDRESS": {
                appDB.Address.put(action.data, "Address");

                return appDB.Address.get();
            }

            case "CREATE_ADDRESS": {
                appDB.Address.post(action.data, "Address");

                return appDB.Address.get();
            }

            default: {
                return appDB.Address.get();
            }
        }
    }
}));


// resulting initial state looks like:
var state = {
    Person: [],
    Organization: [],
    Address: []
};

我们的实际设置如上所示,但有近 100 个减速器。大多数减速器也非常相同。它们唯一的变化通常是操作的类型和要更新的表。

问题

另类商店结构? 我们正在考虑使用单个 reducer 来处理第 3 方数据,并在 Store 结构中公开“Tables”.get()。这样我们的 store 就会有一个更简单的结构(和更少的 reducer),看起来像:

// the application data (built by relational-json)
var appDB = {
    People: {
        get: function() {},
        post: function() {},
        put: function() {},
        delete: function() {}
    },
    Organization: {
        get: function() {},
        post: function() {},
        put: function() {},
        delete: function() {}
    },
    Address: {
        get: function() {},
        post: function() {},
        put: function() {},
        delete: function() {}
    }
};

// example Reducer
store = createStore(combineReducers({
    appDB: function dbReducer(state, action) {
        "use strict";

        switch (action.type) {
            case "UPDATE_PERSON_LIST":
            case "UPDATE_PERSON": {
                appDB.Person.put(action.data, "Person");
                break;
            }

            case "CREATE_PERSON": {
                appDB.Person.post(action.data, "Person");
                break;
            }

            case "UPDATE_ORGANIZATION_LIST":
            case "UPDATE_ORGANIZATION": {
                appDB.Organization.put(action.data, "Organization");
                break;
            }

            case "CREATE_ORGANIZATION": {
                appDB.Organization.post(action.data, "Organization");
                break;
            }

            case "UPDATE_ADDRESS_LIST":
            case "UPDATE_ADDRESS": {
                appDB.Address.put(action.data, "Address");
                break;
            }

            case "CREATE_ADDRESS": {
                appDB.Address.post(action.data, "Address");
                break;
            }

            default: {
                break;
            }
        }

        return Object.keys(appDB).reduce(function(obj, key) {
            obj[key] = appDB[key].get;

            return obj;
        }, {})
    }
}));


// resulting initial state looks like:
var state = {
    appDB: {
        People: function get() {},
        Organization: function get() {},
        Address: function get() {}
    }
};

冲突之处在于apis.apiX 将是上述方法的对象(get)。数据不直接暴露,必须通过Table.get();暴露出来

这在我们的例子中不会造成问题,因为我们使用选择器 (reselect) 获取数据,并且它们知道数据何时发生变化,即使它们必须经过 Table.get();

我感到不安/不确定的是 Redux 预期或完成的任何其他事情。这样的结构会破坏事物吗?

【问题讨论】:

  • 非常有趣。您为此使用什么库?

标签: javascript redux


【解决方案1】:

这两个选项都与 Redux 应用程序的工作方式相反,因为您依赖数据突变而不是返回新对象。

虽然从技术上讲,您可以使用 Redux 对数据进行变异,但我认为在这种情况下,麻烦大于价值,因为您并没有真正从 Redux 中受益。例如,视图无法有效地重绘,因为突变使得无法一眼看出哪些数据已更改。

这就是为什么如果您想将特定的客户端数据库视为事实来源,我建议您不要使用 Redux。只有当 it 是事实的来源时,Redux 才能正常工作。因此,只需直接使用数据库和/或围绕它构建一个更适合您正在尝试做的事情的抽象。

【讨论】:

  • relational-json 也是不可变的。因此,任何“放置”操作都会返回一个新对象,使用旧值和新值的组合。发布、放置或删除操作使用新数组来呈现数据集合。因此,每次修改数据时,都会重新创建包含数组(和修改后的对象)。我觉得它可以与 redux 一起工作的原因正是因为它不会改变数据。 (抱歉,如果没有明确说明)换句话说,如果我是 Table.get(),那么 Table.post();,然后是 Table.get(); get() 的两个返回值;不要引用同一个数组。
  • Table 本身是一个可变对象。否则,您将无法在不使用返回值的情况下调用put(),然后再调用get() 来获取其他内容。它可能在内部使用 Immutable,但 Table 合约是可变的。
【解决方案2】:

据我了解,Redux 不在乎您的商店是什么样子。这是一个抽象。你决定它的外观。您还可以决定 action 如何使用 reducer 影响它。老实说,决定公开方法和/或数据是无关紧要的。只要您坚持自己的设计决策,什么都不会崩溃。我唯一要提防的是,您的应用程序状态是否通过公开方法而不是仅公开数据而真正不可变。

除此之外,知道您的应用程序状态由第三方方法反映意味着您在开发组件时要牢记这一点。它可能不是公认的理想示例,但这并不意味着您不能这样做。反正这是我的看法。

【讨论】:

    【解决方案3】:

    您可能想查看redux-orm。它围绕 Redux 风格的不可变减速器提供了类似“模型”的 API。仍然很新,但目前看来相当有用。

    【讨论】:

      猜你喜欢
      • 2023-01-27
      • 2015-11-10
      • 1970-01-01
      • 2021-02-13
      • 2017-08-22
      • 1970-01-01
      • 2011-06-05
      • 2017-03-05
      • 1970-01-01
      相关资源
      最近更新 更多