How to update value of a specific key in array of objects in react state? - javascript

I'm creating a user role management form like this:
Whenever the user checks or unchecks a permission, I'm trying to put that in the state so that I can send it to my backend server and update the DB.
I'm storing all the rows info in the state in componentWillReceiveProps:
componentWillReceiveProps(nextProps){
if(nextProps.users.items){
this.setState({
userobj : nextProps.users.items['users']
});
const userarr = []
nextProps.users.items['users'].map((i) => {
userarr.push({"employeeid" : i['employeeid'] , "isadmin": i['isadmin'], "isreports" : i['isreports'], "ischarts": i['ischarts'], "ischathistory": i['ischathistory']})
});
this.setState({"list" : userarr});
}
}
Now the state is:
list: Object(4)
​​
0: Object { employeeid: "12345", isadmin: false, isreports: true, … }
​​
1: Object { employeeid: "12346", isadmin: false, isreports: true, … }
​​
2: Object { employeeid: "12347", isadmin: false, isreports: true, … }
​​
3: {…}
There is an onClick event for each checkbox:
<Table.Td>{rows['isadmin'] ? <Checkbox id={rows['employeeid']} name="isadmin" defaultChecked onChange={this.handleChange}></Checkbox> : <Checkbox id={rows['employeeid']} name="isadmin" onChange={this.handleChange}></Checkbox>}</Table.Td>
And this is the code for handleChange:
handleChange(id) {
const checked = id.target.checked;
const empid = id.target.id;
const name = id.target.name;
this.setState(prevState => ({
list: {
...prevState.list,
[this.getIndex(empid, this.state.list, 'employeeid')]: {
...prevState[this.getIndex(empid, this.state.list, 'employeeid')],
[name] : checked
},
}
}));
}
The result is:
list: Object(4)
​​
0: Object { isadmin: true }
​​
1: Object { employeeid: "12346", isadmin: false, isreports: true, … }
​​
2: Object { employeeid: "12347", isadmin: false, isreports: true, … }
​​
3: {…}
What I need to achieve is:
list: Object(4)
​​
0: Object { employeeid: "12345", isadmin: true, isreports: true, … }
​​
1: Object { employeeid: "12346", isadmin: false, isreports: true, … }
​​
2: Object { employeeid: "12347", isadmin: false, isreports: true, … }
​​
3: {…}
I'm new to React and Redux. Any help is appreciated. Thanks in advance. ☺

Replace this:
this.setState(prevState => ({
list: {
...prevState.list,
[this.getIndex(empid, this.state.list, 'employeeid')]: {
...prevState[this.getIndex(empid, this.state.list, 'employeeid')],
[name] : checked
},
}
}));
With this:
this.setState(prevState => ({
list: {
...prevState.list,
[this.getIndex(empid, this.state.list, 'employeeid')]: {
...prevState.list[this.getIndex(empid, this.state.list, 'employeeid')],
[name] : checked
},
}
}));

try updating your handleChange method to this
handleChange(id) {
const checked = id.target.checked;
const empid = id.target.id;
const name = id.target.name;
this.setState(prevState => ({
let list = prevState.list
let user = prevState.list.filter(user => user.employeeid == id)
const userIndex = prevState.list.indexOf(user)
user = {
...user,
isadmin: true
}
list.splice(userIndex, 1) //remove the old user
list.splice(userIndex, 0, user) //put the updated user at same index
this.setState({list})
}));
}

Related

Filter nested array in object javascript express

Considering the below object:
[
{
id: 5fc0be2990a8a12cc0ba0b5c,
projectName: 'E-271120-B',
projectManagaer: '5f7f1ba973ff621da4322248',
dataInici: 2020-11-26T23:00:00.000Z,
dataEntrega: 2020-11-26T23:00:00.000Z,
dtoGlobal: null,
dtoProjecte: null,
archived: false,
created: 2020-11-27T08:51:57.242Z,
updated: 2021-01-25T10:01:18.733Z
tabs: [{permissionsUserID:[250,8]},{permissionsUserID:[3]}],
__v: 3
},
{
tabs: [{permissionsUserID:[3,350]},{permissionsUserID:[15]}],
_id: 5fc0be4690a8a12cc0ba0b5f,
projectManagaer: '5f7f0e69b5862e1a085db388',
projectName: 'E-271120-C',
dataInici: 2020-11-27T23:00:00.000Z,
dataEntrega: 2020-11-29T23:00:00.000Z,
dtoGlobal: null,
dtoProjecte: null,
archived: false,
created: 2020-01-21T08:46:41.958Z,
updated: 2021-01-21T08:46:41.958Z,
__v: 2
},
{
tabs: [{permissionsUserID:[31,350]},{permissionsUserID:[8,893]}],
_id: 5fc0be4690a8a12cc0ba0b5f,
projectManagaer: '5f7f0e69b5862e1a085db388',
projectName: 'E-23410-C',
dataInici: 2020-11-27T23:00:00.000Z,
dataEntrega: 2020-11-29T23:00:00.000Z,
dtoGlobal: null,
dtoProjecte: null,
archived: false,
created: 2020-01-21T08:46:41.958Z,
updated: 2021-01-21T08:46:41.958Z,
__v: 2
}
]
Each object represents a Project. A project has many tabs.
I want to return only the projects that at least one tab contains in permissionsUserID the ID of the user that is logged.
So if the user that is logged has the ID 8, these are the projects I want to obtain:
[
{
id: 5fc0be2990a8a12cc0ba0b5c,
projectName: 'E-271120-B',
projectManagaer: '5f7f1ba973ff621da4322248',
dataInici: 2020-11-26T23:00:00.000Z,
dataEntrega: 2020-11-26T23:00:00.000Z,
dtoGlobal: null,
dtoProjecte: null,
archived: false,
created: 2020-11-27T08:51:57.242Z,
updated: 2021-01-25T10:01:18.733Z
tabs: [{permissionsUserID:[250,8]},{permissionsUserID:[3]}],
__v: 3
},
{
tabs: [{permissionsUserID:[31,350]},{permissionsUserID:[8,893]}],
_id: 5fc0be4690a8a12cc0ba0b5f,
projectManagaer: '5f7f0e69b5862e1a085db388',
projectName: 'E-23410-C',
dataInici: 2020-11-27T23:00:00.000Z,
dataEntrega: 2020-11-29T23:00:00.000Z,
dtoGlobal: null,
dtoProjecte: null,
archived: false,
created: 2020-01-21T08:46:41.958Z,
updated: 2021-01-21T08:46:41.958Z,
__v: 2
}
]
That's the filter I have done:
async getAll(pagination, user) {
try {
const filter = {};
if(pagination.archived) {
filter['archived'] = pagination.archived;
}
if(pagination.search) {
filter['$text'] = {$search: pagination.search}
}
const { Project: projectSchema } = this.getSchemas();
const projectsDocs = await projectSchema.paginate(filter, {
limit: pagination.limit ? parseInt(pagination.limit) : 10,
page: pagination.page ? parseInt(pagination.page) + 1 : 1
});
if (!projectsDocs) {
throw new errors.NotFound('No Projects.');
}
projectsDocs.docs.forEach(element => {
element.tabs.filter( d => d.permissionsUserID.every( c => c.includes(user._id)));
});
return projectsDocs;
} catch (error) {
throw error;
}
},
Here is one way
const data = [...];
const userId = 8;
const result = data.filter((item) => {
const {tabs} = item;
let loggedIn = false;
tabs.forEach((tab) => {
if (tab.permissionsUserID.includes(userId)) {
loggedIn = true;
return true
}
})
return loggedIn;
})
Here's a simple function which should get you what you want.
Filter() returns a subset of the projects list. Some() returns true if at least one of the tabs has the value we're looking for. Includes() returns true if the permissionsUserId list has the user id we want. Chain those together and you get the subset of projects where a tab's permissions has the desired user id.
const data = [
/* list of projects */
],
userId = 8;
function getProjectsForUserId (data, userId) {
return data.filter((project) => {
return project.tabs.some((tab) => {
return tab.permissionsUserID.includes(userId);
});
});
}
console.log(getProjectsForUserId(data, 8));

Angular subscription is not working as I expect

So I have a shop page with a child component called FilterBarComponent and onInit I want it to emit all the category as by default I want all the products in the shop to be rendered, but on my homePageComponent I have a button that allows a user to navigate to the shopPage and view a specific category for e.g a button that says "view shirts". My problem is that the default categories array occurs after the subscriber function finishes and also in the subscriber the event emitter does not fire.
Here is another question of mine that relates to this problem.
Angular EventEmitter is not emitting in subscriber
FilterBarComponent
categories = [];
#Output() filteredCategory = new EventEmitter<any>();
#Output() maxiumPriceEmitter = new EventEmitter<any>();
categorySub: Subscription;
formatLabel(value: number) {
return 'R' + value;
}
constructor(private shopService: ShopService) {}
ngOnInit() {
this.initCategories();
this.filterCategories();
this.updateCategories();
}
filterCategories() {
this.shopService.filterCategories.subscribe(
(fCategory: string) => {
this.categories.map(category => {
category.checked = category.name === fCategory;
});
this.updateCategories();
});
}
initCategories() {
this.categories = [
{ name: 'dress', checked: true, displayName: 'Dresses' },
{ name: 'top', checked: true, displayName: 'Shirts' },
{ name: 'skirt', checked: true, displayName: 'Skirts/Pants' },
{ name: 'purse', checked: true, displayName: 'Purse' },
{ name: 'bag', checked: true, displayName: 'Bags' },
];
}
updateCategories() {
const categories = this.categories
.filter((category) => {
return category.checked;
});
console.log(categories);
this.filteredCategory.emit(categories);
}
in the console at first I get the correct result
but then categories array resets
[{}]
{name: "top", checked: true, displayName: "Shirts"}
[{…}, {…}, {…}, {…}, {…}]
{name: "dress", checked: true, displayName: "Dresses"}
1: {name: "top", checked: true, displayName: "Shirts"}
2: {name: "skirt", checked: true, displayName: "Skirts/Pants"}
3: {name: "purse", checked: true, displayName: "Purse"}
4: {name: "bag", checked: true, displayName: "Bags"}
length: 5
the Observable in ShopService
filterCategories = new BehaviorSubject("category");
I owe this answer to #Józef Podlecki for another question that he answered of mine.
I need to use a BehaviorSubject instead of a regular subject in the ShopService
filterCategories = new BehaviorSubject("all");
Filter Bar Component
ngOnInit() {
this.initCategories();
this.filterCategories();
}
filterCategories() {
this.shopService.filterCategories.subscribe((fCategory: string) => {
if (fCategory === 'all') {
this.updateCategories();
} else {
this.categories.map((category) => {
category.checked = category.name === fCategory;
});
this.updateCategories();
}
});
}

mapping items and flattening into single array in reactjs

Currently I have a reactjs function that simply queries a pouchDB document, gets 7 records and then I'm trying to flatten those records in order to store in state. The problem is that, right now when I console.log docCalories I get this:
(7) [{…}, {…}, {…}, {…}, {…}, {…}, {…}]
0: {caloriesBurned: "5345", createdAt: "2020-03-28T05:15:24.369Z"}
1: {caloriesBurned: "1234", createdAt: "2020-03-28T10:39:16.901Z"}
2: {caloriesBurned: "1122", createdAt: "2020-03-28T10:32:03.100Z"}
3: {caloriesBurned: "1234", createdAt: "2020-03-28T05:16:54.846Z"}
4: {caloriesBurned: "1234", createdAt: "2020-03-28T10:21:31.092Z"}
5: {caloriesBurned: "1234", createdAt: "2020-03-28T05:08:00.791Z"}
6: {caloriesBurned: "1234", createdAt: "2020-03-28T05:07:35.940Z"}
length: 7__proto__: Array(0)
but I want to get something that looks like this:
map: [5345,1234,1122,1234,1234,1234,1234]
So basically one object that contains the 7 numbers from each doc's caloriesBurned value
What am I doing wrong here and how can I properly put these into one array/object?
setMax = () => {
this.state.caloriesDB.db.find({
selector: {
$and: [
{_id: {"$gte": null}},
{caloriesBurned: {$exists: true}},
{createdAt: {$exists: true}}
]
},
fields: ['caloriesBurned', 'createdAt'],
sort: [{'_id':'desc'}],
limit: 7
}).then(result => {
const newDocs = result.docs;
const docCalories = newDocs.map((caloriesBurned) => caloriesBurned)
console.log('this is map');
console.log(docCalories);
}).catch((err) =>{
console.log(err);
});
}
You're returning the entire object in your map function, instead you should only send the caloriesBurned property.
const docCalories = newDocs.map((data) => data.caloriesBurned)
or if you like, we can destructrure data and have
const docCalories = newDocs.map(({caloriesBurned}) => caloriesBurned)
What Dupocas has written in the comments is correct.
newDocs is a list of objects and with this code:
const docCalories = newDocs.map((caloriesBurned) => caloriesBurned)
you will just get another list that is just like newDocs. What you want to return from the map function is a specific key, so try:
const docCalories = newDocs.map(doc => doc.caloriesBurned)
considering docCalories value in m2 by creating map, you can do something like this -
const m2 = new Map(Object.entries([{
0: {
caloriesBurned: "5345",
createdAt: "2020-03-28T05:15:24.369Z"
}
},
{
1: {
caloriesBurned: "1234",
createdAt: "2020-03-28T10:39:16.901Z"
}
},
{
2: {
caloriesBurned: "1122",
createdAt: "2020-03-28T10:32:03.100Z"
}
},
{
3: {
caloriesBurned: "1234",
createdAt: "2020-03-28T05:16:54.846Z"
}
},
{
4: {
caloriesBurned: "1234",
createdAt: "2020-03-28T10:21:31.092Z"
}
},
{
5: {
caloriesBurned: "1234",
createdAt: "2020-03-28T05:08:00.791Z"
}
},
{
6: {
caloriesBurned: "1234",
createdAt: "2020-03-28T05:07:35.940Z"
}
}
]))
var store = [];
Array.from(m2).map(([key, value]) => store.push(value[key].caloriesBurned));
console.log(store);

setState not setting state variable React

I'm trying to set state variable to response data from api call but unable to do so . I have division array in responseJson which i'm trying to set to divisions array in state. I'm getting the responseJson values on console.log but when i'm trying setState({...this.state,divisions:responseJson.division}) i'm not getting any data on console.
state
this.state={
token: data.token,
role: data.role,
userId: data.userId,
organizationId: data.organizationId,
organizationName: data.organization_name,
workspacePP: false,
workspaces: [],
divisions:[],
addWorkspace: null,
isDivisionViewable:false,
divisionName:null
};
function addDivision
addDivision=()=> {
const uri = `${APPURL}/workspace/division/create`;
console.log('dddddd',this.state)
fetch(uri, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
'Authorization': `Bearer ${this.state.token}`
},
body: JSON.stringify({
workspace_id: this.state.workspaces[0].workspace_id,
organization_id: this.state.organizationId,
division:this.state.divisionName
}),
}).then((res)=>res.json()).then(responseJson=>{
if(!responseJson.status){
message.error(responseJson.error);
return;
}
console.log('dddd',responseJson);
this.setState({...this.state,divisions:responseJson.division})
})
console.log(this.state)//returns empty array
}
responseJson
{status: true, division: Array(1), created_at: {…}, user: {…}}
created_at:
updated_at: ["2019-03-09 14:05:26"]
__proto__: Object
division: Array(1)
0: {id: 5, userid: "t863060h", workspace_id: "ROPHV6W", workspace_name:
"workspace", created_at: "2019-03-09 13:39:31", …}
length: 1
__proto__: Array(0)
status: true
user:
created_at: "2019-03-08 18:29:56"
email: "trycatchh#mail.com"
email_verification: 1
id: 1
loginStatus: 0
mobile_otp: 0
mobile_verification: 0
phone: "9632587410"
role: "Admin"
slug: ""
status: 2
team: null
uid: null
updated_at: "2019-03-08 18:29:56"
userid: "t863060h"
username: "tryy catchh"
console.log(this.state)
nName: "tryCatchh", …}
addWorkspace: true
divisionName: "dud"
**divisions**: Array(0)//no data
length: 0
__proto__: Array(0)
isDivisionViewable: true
organizationId: "finalids"
organizationName: "tryCatchh"
role: "Admin"
userId: "t863060h"
workspacePP: false
workspaces: [{…}]
other funtction
showDivision=()=>{
console.log('dddd',this.state.divisions);
}
SetState is asynchronous so To see updated state value you need to
Change
this.setState({...this.state,divisions:responseJson.division})
To
this.setState({
divisions:responseJson.division
}, () => {
console.log(this.state.divisions);//here you will get updated divisions state value
});
Notice your setState is in then function, and will run after the API call response. Your console.log(this.state) will run immediately after calling the API.
if you want to see the final state after the API call, pass a callback func as the second parameter to setState like this:
this.setState({ divisions:responseJson.division }, () => console.log(this.state))
note: you don't need to destructure the state when calling setState, React does it for you already.

Error while splitting Reducer

All below code was in 1 file at the start of refactoring and worked well. I simplified code a little.
My reducers folder:
index.js:
import { combineReducers } from 'redux'
import address from './address'
import questions from './questions'
export default combineReducers({
address,
questions
});
initialState.js:
import { uniqueID } from '../utils/index';
const defaultQuestion = {
title: 'What is the address of the property?',
id: 0,
question_type: 'address'
};
export const initialState = {
questions: [defaultQuestion],
sessionID: uniqueID(),
session: {},
currentQuestion: defaultQuestion,
currentAnswer: '',
addressSelectd: false,
amount: 0,
address: {
address: {},
isPendind: false,
isRejected: false,
isFulfilled: false,
message: '',
}
};
address.js:
import {
ON_SELECT_ADDRESS,
SAVE_ADDRESS_PENDING,
SAVE_ADDRESS_FULFILLED,
SAVE_ADDRESS_REJECTED,
} from '../constants/Constants';
import { initialState } from './initialState'
import { nextQuestion } from './questions'
export default function reduce(state = initialState, action) {
switch (action.type) {
case ON_SELECT_ADDRESS:
return {...state,
currentAnswer: action.payload,
addressSelectd: true
};
case SAVE_ADDRESS_PENDING:
return {...state,
address: {
isPendind: true,
},
};
case SAVE_ADDRESS_FULFILLED:
return {...state,
address: {
isPendind: false,
isRejected: false,
isFulfilled: true,
address: action.payload.address,
},
amount: action.payload.amount,
currentAnswer: '',
currentQuestion: nextQuestion(state),
};
case SAVE_ADDRESS_REJECTED:
// if (action.payload == 'incorrect_address')
return {...state,
currentAnswer: '',
address: {
address: {},
isPendind: false,
isFulfilled: false,
isRejected: true,
message: 'Please find valid address',
},
};
default:
return state;
}
}
questions.js:
import {
ON_CHANGE_ANSWER,
ON_CHANGE_QUESTION,
GET_QUESTIONS,
CREATE_SESSION,
SAVE_ANSWER,
SAVE_CURRENT_ANSWER,
ON_FINISH,
} from '../constants/Constants';
import { initialState } from './initialState'
import { isNullOrUndefined } from 'util';
export const nextQuestion = (state) => {
let nextId = state.currentQuestion.direct_question_id;
if (isNullOrUndefined(nextId)) {
if (state.currentAnswer === 'yes') {
nextId = state.currentQuestion.yes_question_id;
} else if (state.currentAnswer === 'no') {
nextId = state.currentQuestion.no_question_id;
}
}
return state.questions.find((q) => {
return q.id === nextId;
});
}
export default function reduce(state = initialState, action) {
switch (action.type) {
case ON_CHANGE_ANSWER:
return {...state,
currentAnswer: action.payload
};
case ON_CHANGE_QUESTION:
return {...state,
currentQuestion: action.payload
};
case GET_QUESTIONS:
return {...state,
questions: action.payload,
currentQuestion: action.payload[0]
};
case CREATE_SESSION:
return {...state,
session: action.payload,
};
case SAVE_CURRENT_ANSWER:
return {...state,
currentAnswer: action.payload,
};
case SAVE_ANSWER:
return {...state,
currentAnswer: '',
currentQuestion: nextQuestion(state),
};
case ON_FINISH:
return initialState;
default:
return state;
}
}
I have a bunch of errors in Chrome console, like:
Warning: Failed prop type: Invalid prop `questions` of type `object` supplied to `MyApp`, expected `array`.
Warning: Failed prop type: The prop `currentAnswer` is marked as required in `MyApp`, but its value is `undefined`.
But only for questions reducer. And If I add console.log in initialState file, I saw it only 1 time ( I suppose should show 2 times)
Seems questions reducer had not been added to root reducer.
configureStore:
import { createStore, applyMiddleware, compose } from 'redux';
import thunk from 'redux-thunk';
import reducers from '../reducers/index';
import { createLogger } from 'redux-logger';
import DevTools from '../web/containers/DevTools';
const createDevStoreWithMiddleware = compose(
applyMiddleware(thunk),
applyMiddleware(createLogger()),
DevTools.instrument()
)(createStore);
export default function configureStore() {
const store = createDevStoreWithMiddleware(reducers);
return store;
}
Updated:
App.js
import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { connect } from 'react-redux';
import AddressSearch from '../components/AddressSearch';
import FinalScreen from '../components/FinalScreen';
import {
onChangeAnswer,
onChangeQuestion,
getQuestions,
saveAnswer,
createSession,
onFinish
} from '../../actions/actions';
class MyApp extends Component {
static propTypes = {
questions: PropTypes.array.isRequired,
sessionID: PropTypes.string.isRequired,
session: PropTypes.object.isRequired,
currentQuestion: PropTypes.object.isRequired,
currentAnswer: PropTypes.string.isRequired,
address: PropTypes.object.isRequired,
amount: PropTypes.number,
};
componentDidMount() {
this.props.actions.getQuestions();
this.props.actions.createSession();
}
onReset() {
this.props.actions.onFinish();
this.componentDidMount();
}
nextQuestion(text) {
if (text.length > 0) {
this.props.actions.saveAnswer(text);
}
}
renderAnswers() {
const props = this.props;
if (props.currentQuestion.question_type === 'address') {
return <AddressSearch
currentAnswer={props.currentAnswer}
message={props.address.message}
/>;
} else if (props.currentQuestion.question_type === 'text') {
return [
<input
className="question-input"
value={props.currentAnswer}
onChange={(event) => props.actions.onChangeAnswer(event.target.value)}
/>,
<button
className="main-button"
onClick={() => this.nextQuestion(props.currentAnswer)}>
NEXT
</button>
];
} else if (props.currentQuestion.question_type === 'bool') {
return [
<button
className="yes-no-button"
onClick={() => this.nextQuestion('yes')}>
YES
</button>,
<button
className="yes-no-button"
onClick={() => this.nextQuestion('no')}>
NO
</button>
];
} else if (props.currentQuestion.question_type === 'screen') {
return (
<button
className="main-button"
onClick={() => this.onReset()}>
Back
</button>
);
}
}
containerInner() {
if (this.props.currentQuestion.question_type === 'success') {
return <FinalScreen amount={this.props.amount} />;
} else {
return [
<div key={0} className="question">
{this.props.currentQuestion.title}
</div>,
<div key={1} className="answer">
{this.renderAnswers()}
</div>
];
}
}
render() {
return (
<div className="react-native-web">
{this.containerInner()}
</div>
);
}
}
const mapStateToProps = (state) => {
return state;
};
const mapDispatchToProps = (dispatch) => {
return {
actions: {
getQuestions: () => dispatch(getQuestions()),
createSession: () => dispatch(createSession()),
saveAnswer: (text) => dispatch(saveAnswer(text)),
onChangeAnswer: (text) => dispatch(onChangeAnswer(text)),
onChangeQuestion: (obj) => dispatch(onChangeQuestion(obj)),
onFinish: () => dispatch(onFinish()),
}
};
};
export default connect(mapStateToProps, mapDispatchToProps)(MyApp);
In the mapStateToProps,
const mapStateToProps = (state) => {
return state;
};
the state should be split according to its reducers. This is because of combineReducers.
So, when you want to get the actual state when using combineReducers you will have to do something like this -
const mapStateToProps = (state) => {
return state.address; // or state.question
};
If you want to send all the data of the state (i.e. belonging to both reducers), you can do something like this -
const mapStateToProps = (state) => {
return Object.assign({}, state.address, state.question);
};
or you will have to handle it in the reducer code.
NOTE: I haven't tried it, you will have to be careful while doing this because since a separate object is being created, it might cause problems with updating.
EDIT: Some thought about the implementation.
PS: I think the reducer design isn't correct. What I mean is both the address as well as questions reducer have the same initial state. So when you do a combineReducer(), the store.getState() (i.e. the store state) becomes something like this -
state = {
address: {
questions: [{
title: 'What is the address of the property?',
id: 0,
question_type: 'address'
}],
sessionID: 1234,
session: {},
currentQuestion: defaultQuestion,
currentAnswer: '',
addressSelectd: false,
amount: 0,
address: {
address: {},
isPendind: false,
isRejected: false,
isFulfilled: false,
message: '',
}
},
questions: {
questions: [{
title: 'What is the address of the property?',
id: 0,
question_type: 'address'
}],
sessionID: 1234,
session: {},
currentQuestion: defaultQuestion,
currentAnswer: '',
addressSelectd: false,
amount: 0,
address: {
address: {},
isPendind: false,
isRejected: false,
isFulfilled: false,
message: '',
}
}
};
rather than this -
state = {
questions: [{
title: 'What is the address of the property?',
id: 0,
question_type: 'address'
}],
sessionID: 1234,
session: {},
currentQuestion: defaultQuestion,
currentAnswer: '',
addressSelectd: false,
amount: 0,
address: {
address: {},
isPendind: false,
isRejected: false,
isFulfilled: false,
message: '',
}
}
I would strongly advice you to move the common state things (like currentAnswer and currentQuestion) into a separate reducer.
Edit 2: I just verified it with the following code that Object.assign() isn't the correct thing to do.
var address = {
questions: [{
title: 'What is the address of the property?',
id: 0,
question_type: 'address'
}],
sessionID: 12345,
session: {},
currentQuestion: defaultQuestion,
currentAnswer: '',
addressSelectd: false,
amount: 0,
address: {
address: {},
isPendind: false,
isRejected: false,
isFulfilled: false,
message: ''
}
};
var questions = {
questions: [{
title: 'What is the address of the property?',
id: 0,
question_type: 'address'
}],
sessionID: 1234,
session: {},
currentQuestion: defaultQuestion,
currentAnswer: '',
addressSelectd: false,
amount: 0,
address: {
address: {},
isPendind: false,
isRejected: false,
isFulfilled: false,
message: ''
}
};
var result = Object.assign({}, address, questions);
console.log(result);
The output is -
{
"questions": [
{
"title": "What is the address of the property?",
"id": 0,
"question_type": "address"
}
],
"sessionID": 1234,
"session": {},
"currentQuestion": {
"title": "What is the address of the property?",
"id": 0,
"question_type": "address"
},
"currentAnswer": "",
"addressSelectd": false,
"amount": 0,
"address": {
"address": {},
"isPendind": false,
"isRejected": false,
"isFulfilled": false,
"message": ""
}
}
Here, the address has sessionID: 12345, whereas questions has sessionID: 1234, but the result has sessionID: 1234.
Thus the Object.assign() replaces the values set by address with the values of question. This is why it seems to work.
The proper way would be to redesign the reducer such that it has common state in a new reducer.

Categories

Resources