vaibhav
vaibhav

Reputation: 103

How to call async method inside non-async with await?

i'm trying to set the initial state in redux by fetching data from backend. But i'm not getting how can i use async await fetch method to update initial state with fetched data.I tried calling async method inside createReduxStore but unable to resolve the promise.Please help ! Attaching code for reference.

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;
}

For detailed code please refer to.

Any help will be appreciated.

Upvotes: 0

Views: 603

Answers (1)

HMR
HMR

Reputation: 39270

Your createReduxStore function could return a promise resolving to store and you can use that promise in a AsyncProvider component that will return loading as long as the store is not resolved:

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>

Upvotes: 2

Related Questions