how to push an object into array using react - reactjs

This is my initial state constant object, I'm trying to add a new comment items into comments but this code which is not pushing my object into it where i'm doing wrong thanks in advance.
export const comments = [];
export const BlogPostReducer = (state = comments, action) => {
switch (action.type) {
case 'ADD_COMMENT':
return [
...state,
{
name: action.comment.name,
subject: action.comment.subject,
message: action.comment.message
}
];
default:
return state;
}
};
after i used see console here...still im getting empty state
image here

For pushing new object you need to do as
return [
...state,
{
name: action.comment.name,
subject: action.comment.subject,
message: action.comment.message
}
];
This will create and new array, push the object in it and return it

If you want to add it to an array in the immutable way, you should use 'concat'
try below code.
export const comments = [];
export const BlogPostReducer = (state = comments, action) => {
switch (action.type) {
case 'ADD_COMMENT':
return state.concat({name: action.comment.name,subject: action.comment.subject,message: action.comment.message});
default:
return state;
}
};

This way i have achieved,
const addCommentToArray = (state, action) => {
return [...state.comments, {
name: action.comment.name,
subject: action.comment.subject,
message: action.comment.message
}];
}
export const BlogPostReducer = (state = initialState, action) => {
switch (action.type) {
case 'ADD_COMMENT':
return Object.assign({}, state, { comments: addCommentToArray(state, action) });
default:
return state;
}
};

You need to pass comment to store as argument and append to comments.
export const BlogPostReducer = (state, action) => {
switch (action.type) {
case 'ADD_COMMENT':
let { comments } = state;
comments = comments || [];
comments.push(action.comment);
state.comments = comments;
return state;
default:
return state;
}
};

Related

How can i save many objects in Redux?

I get a lot of objects in redax, but only the last one is saved. Each new object replaces the previous one. Can you please tell me how can I save all the objects at once?
I have redux like this
My Reducer
const initianalState = {
};
export const WorldReducer = (state = initianalState, action) => {
switch (action.type) {
case LOAD_PLANET_NAME: {
return {
...state,
homeworld: action.data,
};
}
default: return state;
}
};
My action
export function loadPlanetName(data) {
return {
type: LOAD_PLANET_NAME,
data
};
}
i think it will solve the problem
case LOAD_PLANET_NAME: {
return {
...state,
homeworld: [...state.homeworld,action.data],
};
}

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?

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),
};
}
};

How to add object into array with ES6 ... method ?

I know how to do with push method:
import * as types from '../constants/ActionTypes'
const initialState = {
designBox: [],
}
import * as types from '../constants/ActionTypes'
const initialState = {
designBox: [],
}
export default function(state = initialState, action) {
switch (action.type) {
case types.CREATE_DESIGN_BOX:
let newState = Object.assign({}, state);
newState.designBox.push(action.payload)
return newState
default:
return state
}
}
But I don't know how to do with ... method
Now my code has problem, The designBox can't add objects,
it only has one item, because it just overwritten by new action.payload
import * as types from '../constants/ActionTypes'
const initialState = {
designBox: [],
}
export default function(state = initialState, action) {
switch (action.type) {
// action.payload format -> { width:200,height:300,text:'abc'}
case types.CREATE_BOX:
return {
...state,
designBox: [action.payload]
}
default:
return state
}
}
How can I do this with ... method ??
Spread the the array as well:
return {
...state,
designBox: [...state.designBox, action.payload]
}
Also, your state doesn't need to be an object. If it only contains an array just make it an array:
const initialState = [];
Use array destructor
case types.CREATE_BOX:
return {
...state,
designBox: [...state.designBox,action.payload]
}
There's no way using object spread to manipulate keys, only replace them entirely. You can however refer to the original object when you're overriding keys:
return {
...state,
designBox: state.designBox.concat(action.payload)
}

Resources