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?
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.
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.
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.
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.
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()
);
}
});
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
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With