Javascript Redux-异步加载初始状态
我正试图找到一种最干净的方法来加载来自API调用的Redux存储的初始状态 我知道提供初始状态的典型方法是在页面加载时在服务器端生成初始状态,并将其作为简单对象提供给Redux createStore()。然而,我正在编写一个应用程序,我正计划用Electron打包,所以这不起作用 到目前为止,我所能想到的最好的方法是在创建存储后立即启动一个操作,该操作将转到并请求存储的初始状态——一个操作检索整个初始状态,或者若干个操作,每个操作检索存储的一部分的初始状态。这意味着我的代码看起来像:Javascript Redux-异步加载初始状态,javascript,redux,flux,Javascript,Redux,Flux,我正试图找到一种最干净的方法来加载来自API调用的Redux存储的初始状态 我知道提供初始状态的典型方法是在页面加载时在服务器端生成初始状态,并将其作为简单对象提供给Redux createStore()。然而,我正在编写一个应用程序,我正计划用Electron打包,所以这不起作用 到目前为止,我所能想到的最好的方法是在创建存储后立即启动一个操作,该操作将转到并请求存储的初始状态——一个操作检索整个初始状态,或者若干个操作,每个操作检索存储的一部分的初始状态。这意味着我的代码看起来像: cons
const store = createStore(reducer, Immutable.Map(), middleware);
store.dispatch(loadStateForA());
store.dispatch(loadStateForB());
store.dispatch(loadStateForC());
虽然这会起作用,但它似乎有点粗糙,因此我想知道是否有更好的替代方案,我错过了?我也遇到了同样的问题(也构建了一个电子应用程序)。我的商店的一部分有应用程序设置,这些设置在本地文件系统上持久化,我需要在应用程序启动时异步加载它 这就是我想到的。作为React/Redux的“新手”,我非常有兴趣了解社区对我的方法的想法以及如何改进 我创建了一个异步加载存储的方法。此方法返回一个
Promise
,其中包含store
对象
export const configureStoreAsync = () => {
return new Promise((resolve) => {
const initialState = initialStoreState;//default initial store state
try {
//do some async stuff here to manipulate initial state...like read from local disk etc.
//This is again wrapped in its own Promises.
const store = createStore(rootReducer, initialState, applyMiddleware(thunk));
resolve(store);
});
} catch (error) {
//To do .... log error!
const store = createStore(rootReducer, initialState, applyMiddleware(thunk));
console.log(store.getState());
resolve(store);
}
});
};
然后在我的应用程序入口点中,以下是我如何使用它:
configureStoreAsync().then(result => {
const store = result;
return ReactDOM.render(
<Provider store={store}>
<App store={store}/>
</Provider>,
document.getElementById('Main'));
});
configureStoreAsync()。然后(结果=>{
常数存储=结果;
返回ReactDOM.render(
,
document.getElementById('Main');
});
正如我所说,这是我解决这个问题的天真尝试,我相信一定有更好的方法来处理这个问题。我很想知道如何改进这一点。据我所知,您只有两个选择(逻辑上):
选项1必须使用以下操作完成: 改变状态的唯一方法是发出一个动作,一个对象 描述发生了什么 - 这是你尝试过的,但出于某种原因,你认为它是粗糙的
另一种方法是在异步请求解决后调用
createStore
。一个解决方案已经发布(由@Gaurav Mantri发布),它使用了Promise
对象,这是一个很好的方法
我建议您不要这样做,因为您可能会有多个模块试图
要求或导入您的存储(或存储。分派,或存储。订阅);他们都必须期望得到承诺。第一种方法是最重复的。我的应用程序启动工作流:
在index.html中加载微调器
Ajax检查用户是否登录
在ajax端,呈现根组件
隐藏加载微调器
我通过以下方式实现了这一目标:
使用自定义中间件创建存储,该中间件侦听初始ajax结束操作并调用回调一次
分派初始ajax操作
root.js
const store = createStore(
rootReducer,
applyMiddleware(
...,
actionCallbackOnceMiddleware(INITIAL_AJAX_END, render)
)
)
function render() {
ReactDOM.render(
<Provider store={store}>
<RootComponent/>
</Provider>,
document.getElementById('root')
)
document.getElementById('loading').dispatchEvent(new Event('hide'))
}
store.dispatch(initialAjaxAction());
export default (actionType, callback) => store => next => {
let called = false;
return action => {
next(action);
if (!called && action.type === actionType) {
called = true;
callback();
}
}
}
index.html
<div id="loading">
<span>Loading</span>
<style type="text/css">...</style>
<script>
(function(loading){
loading.addEventListener('hide', function(){
loading.remove();
});
loading.addEventListener('error', function(){
loading.querySelector('span').textContent = "Error";
});
})(document.getElementById('loading'));
</script>
</div>
<div id="root"></div>
加载
...
(功能(加载){
loading.addEventListener('hide',function()){
加载。删除();
});
loading.addEventListener('error',function()){
正在加载.querySelector('span').textContent=“Error”;
});
})(document.getElementById(“加载”);
启动时确实需要加载所有数据吗?您可以根据访问的页面加载部件?