这是一个关于将 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/