Reputation: 2590
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;
Upvotes: 1
Views: 4399
Reputation: 17608
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],
};
}
Upvotes: 3
Reputation: 19762
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
.
Upvotes: 1
Reputation: 5016
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
}
Upvotes: 0