在 Redux + ReactJS 中,我应该在哪里从服务器加载数据?
Where should I load data from server in Redux + ReactJS?
例如,我有两个组件 - ListOfGroupsPage 和 GroupPage。
在 ListOfGroupsPage 中,我从服务器加载组列表并将其存储到 state.groups
在路由中,我为 GroupPage 设置了类似“group/:id”的映射
加载此地址后,应用程序显示 GroupPage,在这里我从 state.groups 获取组的数据(尝试通过 id 找到状态中的组)。
一切正常。
但是如果我重新加载页面,我仍然在页面 /group/2 上,因此会显示 GroupPage。但是状态是空的,所以应用程序找不到组。
在 React + Redux 中加载数据的正确方法是什么?我可以这样看:
1) 加载根组件中的所有数据。流量方面的开销会很大
2) 不要依赖store,尽量在每个组件上加载需要的数据。这是更安全的方式。但我不认为为每个组件加载相同的数据——这是个很酷的主意。然后我们不需要状态 - 因为每个组件都会从服务器
获取数据
3) ???可能在每个组件中添加某种检查 - 首先尝试在存储中找到所需的数据。如果不能 - 从服务器加载。但是它在每个组件中都需要很多逻辑。
那么,在使用 Redux + ReactJS 的情况下,是否有从服务器获取数据的最佳解决方案?
我建议使用 localstorage 在客户端缓存信息。在状态更改时将 Redux 状态或其中的重要部分持久保存到本地存储,并在加载时检查本地存储中的现有记录。由于数据将在客户端上,因此检索起来简单快捷。
我的方法是在商店创建后直接从服务器获取。我通过调度动作来做到这一点。我还使用 thunk 在 *_REQUEST
上设置 isFetching = true
,并在 *_SUCCESS
或 *_FAILURE
后将其设置回 false。这允许我向用户显示进度条或微调器之类的东西。我认为您可能高估了 'traffic' 问题,因为只要您以一种在商店的特定部分为空时不会中断的方式构建组件,它就会异步执行。
您看到的 "can't get groups of undefined" 问题(您在评论中提到)可能是因为您有一个对象并且正在对它执行 .groups
。该对象很可能是空的,因为它还没有被填充。这里有几件事需要考虑:
- 在您的组件中使用三元运算符来检查
someObject.groups
是否为空;或
- 在
someObject.groups
的 initialState 中详细说明为一个空数组。这样,如果您要执行 .map
就不会出错。
- 使用选择器检索组列表,如果
someObject.groups
为空 return 一个空数组。
您可以在 small test app 中查看我如何执行此操作的示例。具体看看:
/src/index.js
初始派送
/src/redux/modules/characters.js
thunk 的使用
/src/redux/selectors/characters.js
用于 CharacterDetails
组件中使用的漫画、系列等的人口
一种方法是使用 redux-thunk
检查 redux 存储中是否存在数据,如果不存在,则发送服务器请求以加载丢失的信息。
您的 GroupPage 组件将类似于
class GroupPage extends Component {
componentWillMount() {
const groupId = this.props.params.groupId
this.props.loadGroupPage(groupId);
}
...
}
在你的行动中...
const loadGroupPage = (groupId) => (dispatch, getState) => {
// check if data is in redux store
// assuming your state.groups is object with ids as property
const {
groups: {
[groupId]: groupPageData = false
}
} = getState();
if (!groupPageData) {
//fetch data from the server
dispatch(...)
}
}
例如,我有两个组件 - ListOfGroupsPage 和 GroupPage。
在 ListOfGroupsPage 中,我从服务器加载组列表并将其存储到 state.groups
在路由中,我为 GroupPage 设置了类似“group/:id”的映射
加载此地址后,应用程序显示 GroupPage,在这里我从 state.groups 获取组的数据(尝试通过 id 找到状态中的组)。 一切正常。
但是如果我重新加载页面,我仍然在页面 /group/2 上,因此会显示 GroupPage。但是状态是空的,所以应用程序找不到组。
在 React + Redux 中加载数据的正确方法是什么?我可以这样看:
1) 加载根组件中的所有数据。流量方面的开销会很大
2) 不要依赖store,尽量在每个组件上加载需要的数据。这是更安全的方式。但我不认为为每个组件加载相同的数据——这是个很酷的主意。然后我们不需要状态 - 因为每个组件都会从服务器
获取数据3) ???可能在每个组件中添加某种检查 - 首先尝试在存储中找到所需的数据。如果不能 - 从服务器加载。但是它在每个组件中都需要很多逻辑。
那么,在使用 Redux + ReactJS 的情况下,是否有从服务器获取数据的最佳解决方案?
我建议使用 localstorage 在客户端缓存信息。在状态更改时将 Redux 状态或其中的重要部分持久保存到本地存储,并在加载时检查本地存储中的现有记录。由于数据将在客户端上,因此检索起来简单快捷。
我的方法是在商店创建后直接从服务器获取。我通过调度动作来做到这一点。我还使用 thunk 在 *_REQUEST
上设置 isFetching = true
,并在 *_SUCCESS
或 *_FAILURE
后将其设置回 false。这允许我向用户显示进度条或微调器之类的东西。我认为您可能高估了 'traffic' 问题,因为只要您以一种在商店的特定部分为空时不会中断的方式构建组件,它就会异步执行。
您看到的 "can't get groups of undefined" 问题(您在评论中提到)可能是因为您有一个对象并且正在对它执行 .groups
。该对象很可能是空的,因为它还没有被填充。这里有几件事需要考虑:
- 在您的组件中使用三元运算符来检查
someObject.groups
是否为空;或 - 在
someObject.groups
的 initialState 中详细说明为一个空数组。这样,如果您要执行.map
就不会出错。 - 使用选择器检索组列表,如果
someObject.groups
为空 return 一个空数组。
您可以在 small test app 中查看我如何执行此操作的示例。具体看看:
/src/index.js
初始派送/src/redux/modules/characters.js
thunk 的使用/src/redux/selectors/characters.js
用于CharacterDetails
组件中使用的漫画、系列等的人口
一种方法是使用 redux-thunk
检查 redux 存储中是否存在数据,如果不存在,则发送服务器请求以加载丢失的信息。
您的 GroupPage 组件将类似于
class GroupPage extends Component {
componentWillMount() {
const groupId = this.props.params.groupId
this.props.loadGroupPage(groupId);
}
...
}
在你的行动中...
const loadGroupPage = (groupId) => (dispatch, getState) => {
// check if data is in redux store
// assuming your state.groups is object with ids as property
const {
groups: {
[groupId]: groupPageData = false
}
} = getState();
if (!groupPageData) {
//fetch data from the server
dispatch(...)
}
}