How to merge the previous state with the new state in redux? - reactjs

How to merge the existing state with the new state in react native using redux?"
i tried these
const Initial_State = { images: [] };
export default (state = Initial_State, action) => {
switch (action.type) {
case 'ImagesFetch':
return {...state, images: action.payload};
default:
return state;
}
}
these two are returning the new state but not showing the previous state
const Initial_State = { images: [] };
export default (state = Initial_State, action) => {
switch (action.type) {
case 'ImagesFetch':
return {...state, images: [...action.payload]};
default:
return state;
}
}
const Initial_State = { images: [] };
export default (state = Initial_State, action) => {
switch (action.type) {
case 'ImagesFetch':
return [...state, ...action.payload.images];
default:
return state;
}
}
and the one is throwing and error, none of the above worked

try this:
const Initial_State = { images: [] };
export default (state = Initial_State, action) => {
switch (action.type) {
case 'ImagesFetch':
return {
images: [...state.images, action.payload]
};
default:
return state;
}
}
Or better to safe if in the future you add to state other properties:
const Initial_State = { images: [] };
export default (state = Initial_State, action) => {
switch (action.type) {
case 'ImagesFetch':
return {
...state,
images: [...state.images, action.payload]
};
default:
return state;
}
}

Related

What are the pros and cons of using a single action to modify multiple values, or an action for each value? Why?

I'm trying to find what would be the best pattern to manage my reducers.
I have the following page:
I know I could've used redux-forms for this, but this is not the point since I only used these fields/form as an example.
We have multiple ways of handling this on redux:
1: having a single action to update those fields values based on the input's name property:
const UPDATE_VALUES = 'UPDATE_VALUES';
const INITIAL_STATE = {
aString: '',
setOfValues1: [],
setOfValues2: []
};
const reducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case UPDATE_VALUES: {
if (action.name === 'setOfValues1' || action.name === 'setOfValues2') {
const array = [...state[action.name]];
array.push(action.value);
return {
...state,
[action.name]: array
};
}
return {
...state,
[action.name]: action.value
};
}
default:
return state;
}
};
2: having multiple actions to each field value:
const UPDATE_A_STRING = 'UPDATE_A_STRING';
const UPDATE_SET_1 = 'UPDATE_SET_1';
const UPDATE_SET_2 = 'UPDATE_SET_2';
const INITIAL_STATE = {
aString: '',
setOfValues1: [],
setOfValues2: []
};
const reducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case UPDATE_A_STRING:
return {
...state,
aString: action.value
};
case UPDATE_SET_1: {
const array = [...state.setOfValues1];
array.push(action.value);
return {
...state,
setOfValues1: array
};
}
case UPDATE_SET_2: {
const array = [...state.setOfValues2];
array.push(action.value);
return {
...state,
setOfValues2: array
};
}
default:
return state;
}
};
and more ways that I'm not aware of.
what would be the good practice/best pattern in this case? Where can I look for, to learn more patterns to situations like these and other situations as well?
What about this?
const UPDATE_VALUES = 'UPDATE_VALUES';
const INITIAL_STATE = {
aString: '',
setOfValues1: [],
setOfValues2: []
};
const setOfValues = ['setOfValues1', 'setOfValues2'];
const reducer = (state = INITIAL_STATE, action) => {
switch (action.type) {
case UPDATE_VALUES: {
if (setOfValues.includes(action.name)) {
return {
...state,
[action.name]: state[action.name].concat(action.value);
};
}
return {
...state,
[action.name]: action.value
};
}
default:
return state;
}
};

React Redux Reducer does not retain other states

I am trying to use stackoverflow api to make my first react redux project. I need to maintain a state like the following:
{
selectedTag: reactjs,
selectedSortOrder: activity,
items:[]
}
My reducer is given below:
const initialState = {
selectedTag: 'C#',
selectedSortOrder: 'activity', items: []
}
function SelectTag(state = initialState, action) {
switch (action.type) {
case SELECTTAG:
// console.log(state);
return Object.assign({}, state, { selectedTag: action.selectedTag });
default:
return state;
}
}
function SelectSortOrder(state = initialState, action) {
switch (action.type) {
case SELECTSORTORDER:
//console.log(state);
return Object.assign({}, state, { selectedSortOrder: action.selectedSortOrder });
default:
return state;
}
}
function ReceivePosts(state = { items: [] }, action) {
switch
(action.type) {
case RECEIVESORTEDPOSTS:
case RECEIVEPOST:
console.log(state);
return Object.assign({}, state, { items: action.items })
default:
return state
}
}
const rootReducer = combineReducers({ ReceivePosts, SelectTag, SelectSortOrder })
And mapStateToProps is:
const mapStateToProps = (state) => {
const selectedTag = state.SelectTag.selectedTag;
const items = (state.ReceivePosts.items);
const tags = (state.ReceiveTags.tags);
const selectedSortOrder = state.SelectSortOrder.selectedSortOrder;
return {selectedTag, items, tags, selectedSortOrder};
}
I have 2 problems here:
a. State does not remember all the data. For eg. suppose I select the tag first and then get items, my state has only items. SelectedTag is not set in the state.
b. I am not sure why mapStateToProps needs the reducer name. Eg: const selectedTag = state.SelectTag.selectedTag;
Actually it should be state.selectedTag. But my code expects the reducer name "SelectTag" to fetch the state value.
What am I doing wrong?
You haven't configured your reducers correctly. The initialState is assigned to all of your reducers which isn't required
const initialState={
selectedTag:'C#',
selectedSortOrder:'activity',
items:[]
}
function SelectTag(state = initialState.selectedTag, action){
switch(action.type){
case SELECTTAG:
return action.selectedTag
default:
return state;
}
}
function SelectSortOrder(state = initialState.selectedSortOrder, action){
switch(action.type){
case SELECTSORTORDER:
return action.selectedSortOrder
default:
return state;
}
}
function ReceivePosts(state = {items:[]}, action){
switch(action.type){
case RECEIVESORTEDPOSTS:
case RECEIVEPOST:
console.log(state);
return Object.assign({}, state, {items:action.items})
default:
return state
}
}
const rootReducer = combineReducers({ReceivePosts, SelectTag, SelectSortOrder})
And in mapStateToProps you would use it like
const mapStateToProps = (state) => {
const selectedTag = state.SelectTag;
const items = (state.ReceivePosts.items);
const tags = (state.ReceiveTags.tags);
const selectedSortOrder = state.SelectSortOrder;
return {selectedTag, items, tags, selectedSortOrder};
}
1. Try this code change
const initialState = {
selectedTag: 'C#',
selectedSortOrder: 'activity',
items: []
}
function SelectTag(state = initialState.selectedTag, action) {
switch (action.type) {
case SELECT TAG:
return {
...state,
selectedTag: action.selectedTag
}
default:
return state;
}
}
function SelectSortOrder(state = initialState.selectedSortOrder, action) {
switch (action.type) {
case SELECTSORTORDER:
return {
...state,
selectedSortOrder: action.selectedSortOrder
}
default:
return state;
}
}
function ReceivePosts(state = { items: [] }, action) {
switch (action.type) {
case RECEIVESORTEDPOSTS:
case RECEIVEPOST:
return {
...state,
items: action.items
}
default:
return state
}
}
const rootReducer = combineReducers({ ReceivePosts, SelectTag, SelectSortOrder });
2. I am not sure why mapStateToProps needs the reducer name. Eg: const selectedTag = state.SelectTag.selectedTag;
Its because when you use combinereducers, you are combining multiple slices of data, then you need to specify the slice from which you want to fetch the data.
const rootReducer = combineReducers({
receivePosts = ReceivePosts,
selectTag = SelectTag,
selectSortOrder = SelectSortOrder
});
Issue: You have not configured your initialstate properly, you are using the same initialstate in SelectTag and also in SelectSortOrder, if the initial state is same then why do you need two reducers?

How can I update the state of reducer?

I want to update the state of activitiesData when ACTIVITIES_SEND_SUCCESS is executed by appending the new data to the end of the object activitiesData.
ActivitiesReducer.js
import {
ACTIVITIES_FETCH_SUCCESS,
ACTIVITIES_SEND_SUCCESS,
SUBACTIVITY_SEND_SUCCESS
} from '../actions/types';
const INITIAL_STATE = { activitiesData: {}, activityCreated: {}, listActivity: {} };
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case ACTIVITIES_FETCH_SUCCESS:
return { ...state, activitiesData: action.payload };
case ACTIVITIES_SEND_SUCCESS:
return { ...state, activityCreated: action.payload };
case SUBACTIVITY_SEND_SUCCESS:
return { ...state, listActivity: action.payload };
default:
return state;
}
};
You can append the data using spread operator syntax like
export default (state = INITIAL_STATE, action) => {
switch (action.type) {
case ACTIVITIES_FETCH_SUCCESS:
return { ...state, activitiesData: action.payload };
case ACTIVITIES_SEND_SUCCESS:
return { ...state, activityCreated: action.payload, activitiesData: {...state.activitesData, ...action.payload } };
case SUBACTIVITY_SEND_SUCCESS:
return { ...state, listActivity: action.payload};
default:
return state;
}
};

How to change my state in my reducer, trying to set a property to true/false

My reducers are split, and in one of them my initial state and reducer looks like:
import Constants from '../constants';
const initialState = {
fetching: true,
};
const boards = (state = initialState, action) => {
switch (action.type) {
case Constants.BOARDS_FETCHING:
return state;
default:
return state;
}
};
export default boards;
How can I change the fetching property to true in the BOARDS_FETCHING case?
Update
My .babelrc looks like:
{
"presets": ["react", "es2015"],
"env": {
"development": {
"presets": ["react-hmre"]
}
}
}
Error:
You need to install transform-object-rest-spread
"plugins": ["transform-object-rest-spread"]
For more, please check babeljs-plugins#transform-object-rest-spread
You should set it in the case Constants.BOARDS_FETCHING clause:
import Constants from '../constants';
const initialState = {
fetching: true,
};
const boards = (state = initialState, action) => {
switch (action.type) {
case Constants.BOARDS_FETCHING:
return {...state, fetching: true};
default:
return state;
}
};
export default boards;
Replace this:
const boards = (state = initialState, action) => {
switch (action.type) {
case Constants.BOARDS_FETCHING:
return state;
default:
return state;
}
};
to:
const boards = (state = initialState, action) => {
switch (action.type) {
case Constants.BOARDS_FETCHING:
return Object.assign({},state,action.fetching);
default:
return state;
}
};

Redux nested state

I have read many articles and examples, but I dont find a method to simplify a nested state. Is this possible to udpate a state without using a rest operator by property like the partial code below ?
const initialState = {
currentTag: 'fr-FR',
locales: {
components: [],
},
};
const setComponentsLocales = (state, payload) => ({
...state,
[payload.oid]: payload.locales,
});
const localesReducer = (state, action) => {
switch (action.type) {
case types.SET_COMPONENT_LOCALES:
return {
...state,
components: setComponentsLocales(state.components, action.payload),
};
default:
return state;
}
};
export default (state = initialState, action) => {
switch (action.type) {
case types.SET_LANGUAGE:
return {
...state,
currentTag: action.payload.tag,
};
default:
return {
...state,
locales: localesReducer(state.locales, action),
};
}
};

Resources