How can I keep previous state and add a new state to the previous state in Redux reducers?

redux store
redux reducers best practices
redux actions
react redux reducer example
redux tutorial
...state redux meaning
where redux store data
redux previous state

The below is one of my reducers. In the function applySetRandomImages, I want to access previous state of randomImages to add a new state of randomImages with the previous state.

How can I do that? does the reducer function in Redux provides some call back function for that? or should I implement that on my own?

// ACTIONS
const SET_RANDOM_IMAGES = "SET_RANDOM_IMAGES";

// ACTION CREATORS
function setRandomImages(randomImages) {
  return {
    type: SET_RANDOM_IMAGES,
    randomImages
  };
}

// API ACTIONS
function getRandomImages(page) {
  return (dispatch, getState) => {
    fetch(`/boutiques/random-images/?page=${page}`)
      .then(response => response.json())
      .then(json => dispatch(setRandomImages(json.results)))
      .catch(err => console.log(err));
  };
}

// INITIAL STATE
const initialState = {};

// REDUCER
function reducer(state = initialState, action) {
  switch (action.type) {
    case SET_RANDOM_IMAGES:
      return applySetRandomImages(state, action);
    default:
      return state;
  }
}

// REDUCER FUNCTIONS
function applySetRandomImages(state, action) {
  const { randomImages } = action;
  return {
    ...state,
    randomImages    <--- I need to merge the randomImages with a new state of randomImages
  };
}

// EXPORTS
const actionCreators = {
  getRandomImages,
};
export { actionCreators };

// DEFAULT REDUCER EXPORTS
export default reducer;

You can merge randomImages by spreading the old state and the new one into a new array:

function applySetRandomImages(state, action) {
  const { randomImages } = action;
  return {
    ...state,
    randomImages: [...state.randomImages, ...randomImages],
  };
}

An intro to Redux and how state is updated in a Redux application, How can initial state be passed to store the using the createStore function? There is no “right” answer for this. Some users prefer to keep every single piece of data in Redux, to maintain a fully serializable and controlled version of their application at all times. Others prefer to keep non-critical or UI state, such as “is this dropdown currently open”, inside a component's internal state.

I want to access previous state of randomImages to add a new state of randomImages with the previous state

return {
    ...state,
    ...randomImages
};

If previous state was:

{
    a: 1,
    b: 2,
    c: 3
}

And randomImages is:

{
    d: 4,
    e: 5
}

Then the returned new state will be

{
    a: 1,
    b: 2,
    c: 3,
    d: 4,
    e: 5
}

Organizing State, Should I put form state or other UI state in my store? and concept of reducers to the task of updating local component state as well, along the lines of this. It's important to return the previous state for any unknown action. # Note on Object.assign. Object.assign () is a part of ES6, and is not supported by older browsers. To support them, you will need to either use a polyfill, a Babel plugin, or a helper from another library like _.assign ().

Separate actions, reducers and types into their own folders.

types/index.js

export const SET_RANDOM_IMAGES = "SET_RANDOM_IMAGES";

actions/imageActions.js

import * as types from '../types';

export const getRandomImages = page => dispatch => (
  fetch(`/boutiques/random-images/?page=${page}`)
    .then(response => response.json())
    .then(json => dispatch({ type: types.SET_RANDOM_IMAGES, payload: json.results })))
    .catch(err => console.log(err))
)

From within a component, you will connect to redux state (state.images or state.images.collection) and dispatch the action (getRandomImages):

import React, { Component } from 'react';
import { connect } from 'react-redux';
import { getRandomImages } from '../actions/imageActions';

class Example extends Component {

   componentDidMount = () => this.props.getRandomImages(); // dispatches action creator

   render = () => (
       <div>
         { /* 
             The props below are redux state passed into 
             the component via the connect function
         */ }
         {this.props.images.map(image => (
           <img src={image.src} alt="image.name" />
         ))}
         {this.props.collection.map(image => (
           <img src={image.src} alt="image.name" />
         ))}
       </div>
   )
}

export default connect(state => ({ 
  images: state.images, // pulled from redux state (state.images => this.props.images)
  collection: state.images.collection // pulled from redux state (state.images.collection => this.props.images.collection)
}), { getRandomImages})(Example)

It will then trigger the AJAX request, then return a type and payload to your reducer:

reducers/index.js

import * as types from '../types'

// overwrite images for each successful fetch request
const imageReducer(state={}, {type, payload}) {
  switch (type) {
    // spread out any previous state, then spread out the payload (json.results)
    case types.SET_RANDOM_IMAGES: return { ...state, ...payload }
    default: return state;
  }
}

// or append images on each successful fetch request...
const imageReducer(state={}, {type, payload}) {
  switch (type) {
    case types.SET_RANDOM_IMAGES: 
      return { 
        ...state,  // spread out any previous state
        collection: [ 
          ...state.collection, //  then spread out any previous "collection" state, 
          ...payload // then spread/append the payload (json.results) 
        ]
      }
    default: return state;
  }
}

export default combineReducers({
  images: imageReducer
});

The reducer will then spread out any previous imageReducer state, then append the res.results to it via payload. Now it exists in redux as state.images or state.images.collection. This is then pulled from redux state and into the component above as this.props.images or this.props.images.collection.

The Definitive Guide to Redux Persist, The reducer (state, action) => state signature makes it natural to implement generic “reducer enhancers” or Undo and Redo, you want to keep track of the history of this state at different points in time. What are the past (and future) states in the undo stack? Insert the old present state at the beginning of the future . The previous state received by the reducer has unexpected type of "Function". Expected argument to be an object with the following keys: "auth", "common", "home" Here is code:

Initializing State, 3 Answers. Separate actions , reducers and types into their own folders. import * as types from '../types' // overwrite images for each successful fetch request const imageReducer(state={}, {type, payload}) { switch (type) { // spread out any previous state, then spread out the payload (json. results) case types. You can also use a utility such as reduce-reducers to run combineReducers to handle most actions, but also run a more specialized reducer for specific actions that cross state slices. Async action creators such as redux-thunk have access to the entire state through getState() .

Implementing Undo History, I glossed over how state changes occur in the previous chapter. In Redux we say that actions (reports) are "dispatched" to the store to let it know If you find yourself creating actions that sound like a a function call like Similarly, in Redux a reducer takes the starting state and an item to process, and return the new state. As far as my understanding goes, this block of text is part of my 'state'. And because of this, I would have to create a new copy of these 20k characters, and then add new ones to the end/delete old ones of the start, everytime some new characters appear. This doesn't seem very efficient or processor friendly. Is it that:

How can I keep previous state and add a new state to the previous , In this post we will take a look at using Redux for managing the state in React apps. Patrick already wrote a great article on Redux so I will keep this short. the array we create a brand new array containing all the previous state in one reducer with a single action acting on the state tree but adding new  Actions and reducers: updating state. I glossed over how state changes occur in the previous chapter. Let's look a bit deeper. In Redux all changes to the application state happen via an "action." An "action" in Redux terms is simply "a thing that happened" expressed as a plain JavaScript Object. For example: { type: 'LOGIN_SUCCEEDED'}

Comments
  • So, you have randomImages in your state and you want to merge it with the ones come with your action? Is it an array or an object?
  • Yes, I want to merge the upcoming one with the existing one. It's array.
  • that's what I tried, but when I console.log it, it returns undefined
  • Didn't check if randomImages exists at the very beginning!. Thanks!
  • You are welcome. I fixed a mistake in my answer. I forgot to spread the new randomImages.