Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Async initial state React-Redux Redux-Thunk

Using React, Redux, Redux-thunk I want to have an initial state through a server request (API call) but I cannot seem to get this to work.

What I have got so far:

var Redux = require('redux');
var carReducer = require('./reducers/cars');
var thunk = require('redux-thunk').default;

var initialState = require('./reducers/initialState');

var rootReducer = Redux.combineReducers({
    cars: carReducer
});

module.exports = Redux.applyMiddleware(thunk)(Redux.createStore)(rootReducer, initialState.loadInitial());

This is my initial store creation. My InitialState looks like this:

var $ = require('jquery');

module.exports = {
    loadInitial: loadInitial
};

function loadInitial() {
    return {
        cars: [
            {}
        ]
    }
}

When I try to turn this loadInitial into a $.get('api/...'), Redux tells me that I need an initial state in order for it to work.

In my reducer I have a load method:

function updateReducer(state, action) {
    switch (action.type) {
        case 'load':
            return action.data;
        case 'update':
            return updateCars(action.data, state);
        default:
            return action.data || initialState.loadInitial().cars;
    }
};

But again, if I use - as a default - an async call, it does not seem to work.

What I actually want is for my store to be initialized with whatever comes from the database. This is needed for my HandsonTable, since I pass the properties to the table and as I have it now, it will only render me one row because my initial state has only one object.

Weird part about this is that when I click on the table, it actually gets me all my rows because the data is loaded, but I'm guessing just too late.

Anyway, my question here is, how do I initialize my store through an api call to my backend?

like image 311
Tikkes Avatar asked May 25 '16 11:05

Tikkes


People also ask

Is redux-thunk async?

Writing middleware for Redux is a powerful tool; Redux Thunk is one of the most widely-used middleware for async actions. Thunk is also a default async middleware for Redux Toolkit and RTK Query. If you want a simple API integration for your Redux apps, RTK Query is a highly recommended option.

How do you handle async actions in Redux?

Redux Async Data Flow​ Just like with a normal action, we first need to handle a user event in the application, such as a click on a button. Then, we call dispatch() , and pass in something, whether it be a plain action object, a function, or some other value that a middleware can look for.

How do I set Redux state to initial state?

You can set it at the reducers . Reducers can also set initialState by looking at the incoming state argument (which would be undefined if createStore is not called with initialState ) and returning the values they would like to use as default.

Is redux-thunk necessary?

A very common pattern in Redux is to use things called a Thunks, which are a way of wrapping up certain logic of a subroutine in a single function.


2 Answers

You can give it a blank initial state (empty object or perhaps just a loading message) and when your API call comes back, you can update the state and your component will redraw with its new data as a consequence. The other thing you can do is not initialize your component until the call returns with your data.

EDITED TO INCLUDE EXAMPLE

In one of your lifecycle methods of your component (perhaps even in getInitialState):

getInitialState: function() {
  var oThis = this;

  $.get({
    url: 'api...',
    success: function (...) {
      oThis.setState({...data returned by server});
    }
  });

  return {};
}

Or, something along these lines:

$.get({
  url: 'api...',
  success: function (...) {
    var oStore;

    // oStore = response from server

    ReactDOM.render(
      <ReactRedux.Provider store={oStore}>
        <MyComponent/> 
      </ReactRedux.Provider>
      , document.getElementById()
    );
  }
});
like image 163
Christoph Avatar answered Sep 22 '22 06:09

Christoph


For redux initial state you can't pass async value, so you need to pass some static empty object (like you have in your example) and call an action to get initial state from server and replace your state. To simplify all this process you can use redux async initial state middleware

like image 40
Alexandr Subbotin Avatar answered Sep 25 '22 06:09

Alexandr Subbotin