我有一个 React/Redux 应用程序,它从 API 加载
cats
列表。
数据被加载到组件中,如下所示:
// thunk, etc omitted for clarity.
componentDidMount() {
if(!this.props.loaded){
this.props.actions.loadRooms();
}
}
从这里获取道具:
function mapStateToProps(state, ownProps) {
return {
cats: state.cats.items,
loaded: state.cats.loaded
}
}
假设如下:
1)
cats
将需要在一个不同的、完全独立的组件中,该组件不是当前组件的子组件。
2) 我无法知道将首先安装哪个
cats
需要的组件。
if(!this.props.loaded)
有用吗?换句话说,如果两者都首先检查现有的商店数据,那么当其他路由挂载时,它是否可以节省我对 API 的理论调用?
如果检查有用,有更好的方法吗?
是的,我想让你的 redux 操作看起来像:
GET_CATS
、GET_CATS_SUCCESS
和GET_CATS_ERROR
。
GET_CATS
会将 redux 存储中的 loading
状态设置为 true
,这样您就可以在相应的 componentDidMount()
函数中查询它,并且仅当 loading
为 false 时才调用 api。我认为这是一种相当常见的做法。
这完全取决于你如何在 redux 中处理异步数据获取,如果两个同级组件都在监听代表
cats
的状态部分,你可以这样做:
// Component A and Component B might have something like this
// they both subscribe to the same portion of the state so, if
// data is already available then you don't need to do fetch it again.
...
componentDidMount() {
if (this.props.cats.length === 0) {
this.props.actions.loadRooms();
}
}
...
如果您使用
redux-thunk
那么您可以在 action
级别进行控制:
function loadRooms() {
return (dispatch, getState) => {
if (getState().cats.length === 0) {
dispatch(loadRoomsPending());
fetchMyData(...args)
.then((res) => dispatch(loadRoomsSuccess(res))
.catch((err) => dispatch(loadRoomsError(err));
}
}
}
// Component A and Component B
...
componentDidMount() {
this.props.actions.loadRooms();
}
...
在这里,您可以使用
getState()
访问当前状态,因此检查数据是否可用是很常见的。现在这种方法带有一些样板文件,从长远来看可能会变得乏味(它需要您编写另外三个函数loadRoomsPending
,loadRoomsSuccess
,loadRoomsError
)。这样您的组件就不必手动检查它。或者,如果你喜欢它更明确或更干净,你可以尝试一下我实现的中间件,我对所有这些样板感到有点沮丧,所以使用 redux-slim-async
你可以这样做:
function loadRooms() {
return {
types: [
actionTypes.LOAD_ROOMS_PENDING,
actionTypes.LOAD_ROOMS_SUCCESS,
actionTypes.LOAD_ROOMS_ERROR,
],
callAPI: fetch(...args).then(res => res.json()),
shouldCallAPI: (state) => state.cats.length === 0,
};
}
这会通过符合 FSA 的操作为您处理所有事情,并且非常清楚发生了什么。如果你正确设置它,你可以让它变得更好:
function loadRooms() {
return {
typePrefix: actionTypes.LOAD_ROOMS,
callAPI: fetch(...args).then(res => res.json()),
shouldCallAPI: (state) => state.cats.length === 0,
};
}
这将触发挂起的、成功的和错误的请求,格式为
${typePrefix}_PENDING
、${typePrefix}_SUCCESS
、${typePrefix}_ERROR
,您可以在这里找到中间件。但无论如何,只要使用你认为最适合你的用例的任何东西,我想分享这项工作,因为这是一种挫败感,促使我构建一个中间件来处理它。请记住,我对您的案例做了一些假设,因此如果我完全不同意,请告诉我。
如果我正确理解你的问题,你希望能够查看是否有一个单独的类已加载其数据。如果是,则不要再次调用 API 加载猫。
有两种方法可以做到这一点,假设 COM1 和 COM2 是您的组件。
返回整个
state
,而不是仅返回两个组件所需的特定变量:
返回状态
然后引用每个组件中的猫:
this.props.COM1.cats.items
this.props.COM2.cats.items
function mapStateToProps(state, ownProps) {
let cats = state.COM1.cats.items;
let loaded: state.cats.loaded;
let otherCats = state.COM2.cats.items;
return {
cats,
otherCats,
loaded
}
}
就我而言,我只是避免直接将数据保存到状态中,而是在对象内添加数据。 像以前一样:
const initialData = [];
state.push(...);
之后:
const initialData = {
data: []
};
state.data.push(....);