我正在尝试通过从后端获取数据来设置 redux 中的初始状态。但我不明白如何使用异步等待获取方法来更新获取数据的初始状态。我尝试在 createReduxStore 中调用异步方法,但无法解决承诺。请帮忙!附上代码供参考。
Index.tsx
import React from "react";
import ReactDOM from "react-dom";
import { Provider } from "react-redux";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
import createReduxStore from "./redux/store/store";
import initialState from "./redux/store/initialState";
import { IApplicationState } from "./models/applicationState";
const defaultState: IApplicationState = initialState;
const store = createReduxStore(defaultState, true);
ReactDOM.render(
<Provider store={store}>
<App/>
</Provider>
, document.getElementById("rootdiv"));
Store.ts
import { applyMiddleware, createStore, Store } from "redux";
import thunk from "redux-thunk";
import rootReducer from "../reducers";
import { IApplicationState } from "../../models/applicationState";
import { mergeInitialState } from "../middleware/fetchData";
import { Env } from "../../common/environment";
export default function createReduxStore(
initialState?: IApplicationState,
useLocalStorage: boolean = false): Store {
const paths: string[] = ["appSettings", "connections", "recentProjects", "prebuiltSettings"];
data = this.getData();
initialstate["appSettings"]=data;
let middlewares = [thunk];
if (useLocalStorage) {
const localStorage = require("../middleware/localStorage");
const storage = localStorage.createLocalStorage({paths});
middlewares = [
...middlewares,
storage,
];
}
return createStore(
rootReducer,
useLocalStorage ? mergeInitialState(initialState, paths) : initialState,
applyMiddleware(...middlewares),
);
}
async function getData(){
const request = await fetch("url",{
method:'GET',
headers:{
'Accept':'application/json',
'Content-Type':'application/json',
}
});
if(request.ok){
var response = await request.json();
}
return response;
}
详细代码请refer to。
任何帮助将不胜感激。
答案 0 :(得分:2)
您的 createReduxStore 函数可以返回解析为存储的承诺,您可以在 AsyncProvider 组件中使用该承诺,只要存储未解析,该组件就会返回加载:
const { Provider, useSelector } = ReactRedux;
const { createStore, applyMiddleware, compose } = Redux;
const someAsync = () =>
new Promise((r) => setTimeout(() => r([1, 2, 3]), 2000));
const reducer = (state) => state;
function createReduxStore() {
const composeEnhancers =
window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
return someAsync().then((asyncData) =>
createStore(
reducer,
{asyncData},
composeEnhancers(
applyMiddleware(() => (next) => (action) =>
next(action)
)
)
)
);
}
const asyncStore = createReduxStore();
const AsyncProvider = ({ children }) => {
const [store, setStore] = React.useState(false);
//effect that will set local store state with
// redux store when asyncStore resolves
React.useEffect(() => {
asyncStore.then((store) => setStore(store));
//this is missing catch to be used if something goes wrong
// you may want to solve that in your createReduxStore function
// if something goes wrong then provide the error in initial state
}, []);
//will only render provider when store is resolved
return store ? (
<Provider store={store}>{children}</Provider>
) : (
'state is loading'
);
};
const App = () => {
const reduxState = useSelector((state) => state);
return (
<div>
<h1>In App, state is:</h1>
<pre>{JSON.stringify(reduxState, undefined, 2)}</pre>
</div>
);
};
ReactDOM.render(
<AsyncProvider>
<App />
</AsyncProvider>,
document.getElementById('root')
);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.4/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.4/umd/react-dom.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/redux/4.0.5/redux.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-redux/7.2.0/react-redux.min.js"></script>
<div id="root"></div>