使用包含承诺的 createselector 反应 redux 容器
React redux container with createselector that contains a promise
我有一个连接到商店的容器,每秒更新一次:
return ({ match, ui }, { matchId }) => ({
value: match.getIn([matchId, 'masterCurrentTime'], 0), // about every second
min: ui.get('seekStart'),
max: ui.get('seekEnd'),
highlightList: selectHighlights(matchId) // i only want to do this on first render
});
然而,其中一个属性 (highlightList) 执行以下两项操作之一:
1) return 来自 sessionStorage 的值
或
2) 下载一个文件,将其保存到 sessionStorage,然后 returns 它
当然我不想每秒钟都这样做,只有第一次。
我创建了一个这样的选择器
const selectHighlights = createSelector(
matchId => matchId,
matchId => {
if (matchId !== null) {
getTimelineWithFilter(matchId, ['round_start'])
.then(timeline => {
console.log(timeline);
return timeline;
})
.catch(error => {
throw new Error('failed to load highlights', error);
});
}
return null;
}
);
但是不行,没有渲染。
但是,如果我做一个替代版本,我将结果存储在一个变量中,然后查询它,事情就可以了。它只运行一次并按我喜欢的方式执行
// highlightList: currentTimeline === undefined ? loadHighlights(matchId) : currentTimeline,
我只是想学习如何以正确的方式做到这一点,有这方面知识的人可以给我一些最佳实践技巧吗?
如何在 React-Redux 应用程序中处理承诺?
假设您有一个 action creator 用于从某些 API 获取数据。您将从您的组件调度操作(加载/点击/其他事件)。
export function loadData(key) {
return {
types: [LOAD_DATA, LOAD_DATA_SUCCESS, LOAD_DATA_FAIL]
promise: () => fetch(...), // API call that returns a promise
key,
}
}
现在在创建 store
时创建一个 middleware for promise based operations. Make sure you applyMiddleware
。
The most common use case for middleware is to support asynchronous
actions without much boilerplate code or a dependency on a library
like Rx. It does so by letting you dispatch async actions in addition
to normal actions.
export default function clientMiddleware() {
return ({ dispatch, getState }) => next => (action) => {
if (typeof action === 'function') {
return action(dispatch, getState);
}
const { promise, types, ...rest } = action;
if (!promise) {
return next(action);
}
const [REQUEST, SUCCESS, FAILURE] = types;
next({ ...rest, type: REQUEST });
const actionPromise = promise();
actionPromise
.then(result => next({ ...rest, result, type: SUCCESS }))
.catch(error => next({ ...rest, error, type: FAILURE }));
return actionPromise;
};
}
最后这是你的 initialState:
const initialState = {
isLoading: false,
isLoaded: false,
data: {},
error: null,
};
和减速器:
case LOAD_DATA:
return {
...state,
isLoading: true
};
case LOAD_DATA_SUCCESS:
return {
...state,
isLoading: false,
isLoaded: true,
data: action.result,
};
case LOAD_DATA_FAIL:
return {
...state,
isLoading: false,
isLoaded: false,
error: action.error
};
我有一个连接到商店的容器,每秒更新一次:
return ({ match, ui }, { matchId }) => ({
value: match.getIn([matchId, 'masterCurrentTime'], 0), // about every second
min: ui.get('seekStart'),
max: ui.get('seekEnd'),
highlightList: selectHighlights(matchId) // i only want to do this on first render
});
然而,其中一个属性 (highlightList) 执行以下两项操作之一:
1) return 来自 sessionStorage 的值
或
2) 下载一个文件,将其保存到 sessionStorage,然后 returns 它
当然我不想每秒钟都这样做,只有第一次。
我创建了一个这样的选择器
const selectHighlights = createSelector(
matchId => matchId,
matchId => {
if (matchId !== null) {
getTimelineWithFilter(matchId, ['round_start'])
.then(timeline => {
console.log(timeline);
return timeline;
})
.catch(error => {
throw new Error('failed to load highlights', error);
});
}
return null;
}
);
但是不行,没有渲染。 但是,如果我做一个替代版本,我将结果存储在一个变量中,然后查询它,事情就可以了。它只运行一次并按我喜欢的方式执行
// highlightList: currentTimeline === undefined ? loadHighlights(matchId) : currentTimeline,
我只是想学习如何以正确的方式做到这一点,有这方面知识的人可以给我一些最佳实践技巧吗?
如何在 React-Redux 应用程序中处理承诺?
假设您有一个 action creator 用于从某些 API 获取数据。您将从您的组件调度操作(加载/点击/其他事件)。
export function loadData(key) {
return {
types: [LOAD_DATA, LOAD_DATA_SUCCESS, LOAD_DATA_FAIL]
promise: () => fetch(...), // API call that returns a promise
key,
}
}
现在在创建 store
时创建一个 middleware for promise based operations. Make sure you applyMiddleware
。
The most common use case for middleware is to support asynchronous actions without much boilerplate code or a dependency on a library like Rx. It does so by letting you dispatch async actions in addition to normal actions.
export default function clientMiddleware() {
return ({ dispatch, getState }) => next => (action) => {
if (typeof action === 'function') {
return action(dispatch, getState);
}
const { promise, types, ...rest } = action;
if (!promise) {
return next(action);
}
const [REQUEST, SUCCESS, FAILURE] = types;
next({ ...rest, type: REQUEST });
const actionPromise = promise();
actionPromise
.then(result => next({ ...rest, result, type: SUCCESS }))
.catch(error => next({ ...rest, error, type: FAILURE }));
return actionPromise;
};
}
最后这是你的 initialState:
const initialState = {
isLoading: false,
isLoaded: false,
data: {},
error: null,
};
和减速器:
case LOAD_DATA:
return {
...state,
isLoading: true
};
case LOAD_DATA_SUCCESS:
return {
...state,
isLoading: false,
isLoaded: true,
data: action.result,
};
case LOAD_DATA_FAIL:
return {
...state,
isLoading: false,
isLoaded: false,
error: action.error
};