javascript - Redux Store 和第三方数据结构

标签 javascript redux

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

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

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

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

因此,我们的 reducer 通过与第 3 方模块合作来“更新状态”。繁重的工作是由第 3 方完成的,reducer 基本上总是返回 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 。大多数 reducer 也非常相同。他们唯一的变化通常是操作的类型和要更新的表。

问题

替代商店结构? 我们正在考虑使用单个 reducer 来处理第 3 方数据,并在 Store 结构中公开“Tables”.get()。这样我们的商店就会有一个更简单的结构(和更少的 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();

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

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

最佳答案

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

虽然从技术上讲,您可以使用 Redux 改变数据,但我认为在这种情况下,麻烦大于其值(value),因为您并没有真正获得 Redux 的好处。例如, View 无法有效地重绘,因为突变使得无法一眼看出哪些数据已更改。

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

关于javascript - Redux Store 和第三方数据结构,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/34655972/

相关文章:

javascript - Crafty.js 显示白屏

JavaScript setInterval() 卡住了我的网站

Javascript 正则表达式不返回全局结果

javascript - 如何使用传递给 reducer 的事件对象验证 reducer 内的单选按钮?

javascript - Node.js Express Jade 改进 TTFB?

javascript - React Redux - 在发送问题之前快速闪现之前的状态

javascript - fetch api 从服务器获取错误消息而不是通用消息

javascript - React-Redux : how to make ReCaptcha a required field

javascript - redux-form 中的同名字段

javascript - ng-change 和 onchange 不适用于 <输入类型 ="file">