I have an empty state
object that is instantiated with default empty fields on app start.
It contains an empty array named users
.
const state = {
users: []
}
On start I send some commands to server and server then sends data in response.
As I need to populate users
, I think I just want to replace the whole users array with a new one that is received from server.
I read that in redux you take the current state, apply some changes to it and return a new state. It sounds good when I want to, say, change user password, then I would call an action like this:
{
action: 'CHANGE_PASSWORD',
user: 'john',
password: 'karamba',
}
It would be managed by the dispatcher, where a user john
would be found in the current state and the password would be replaced with the new one.
But is this correct for the scenario where I want to load some initial data?
If so, how would an action look like?
{
action: 'FETCH_USERS'
}
And then the reducer would replace the whole users
array?
Let just cover some basics first
(State,Action) => State;
So what does your actions look like for Async Flows (where you are retrieving data from network request)? When Async flow you using need to use some type of middleware http://redux.js.org/docs/advanced/Middleware.html.
In the actions below I have used a middleware called thunk.
actions.js:
export function receiveAllProducts(users){
return {
type: 'RECEIVED_ALL_USERS',
users: users
}
}
export function fetchALLUserData(){
return thunkLoadAllUserData;
}
const thunkLoadAllUserData = (dispatch) => {
let users = [];
users = //Some network request to get data
dispatch(receivedAllUserData(users));
});
}
So you would dispatch an action to fetchALLUserData
, which returns a thunk
function (redux middleware for Asynchronous Flows) to retrieve the users, which then calls receivedAllUserData
action that as a type : 'RECEIVED_ALL_USERS'
. This type is is captured by your reducer, which uses a pure function and Object.assign to return a new state (with the new users).
What does the reducer pure function look like ? reducers.js:
const initialState = {}
export default (currentState = initialState, action = {}) => {
switch (action.type) {
case 'RECEIVED_ALL_USERS':
return Object.assign({}, currentState, {
users: action.users,
});
case 'RECEIVE_ALL_PRODUCTS':
return Object.assign({}, currentState, {
productsAsObject: action.productsObject,
});
// ...other actions
default:
return currentState;
}
}
The Object.assign() method is used to copy the values of all enumerable own properties from one or more source objects to a target object. And therefore will copy the whole currentState and override your users attributes with the fetched user
Alternatively you can also use the object spread operator to update the state: http://redux.js.org/docs/recipes/UsingObjectSpreadOperator.html