Problem
I have a nested state which is needed to set its state by a key’s value:
state = {
income_source: {
type: 'text', label_name: 'Income Source', value: '', helper: 'dropdown',
},
employment_status: {
type: 'text', label_name: 'Employment Status', value: '', helper: 'dropdown',
},
...
I’m getting a huge list from a get_financial_assessment
object and the code becomes messy when I tried to setState
in componentDidMount():
async componentDidMount() {
let { get_financial_assessment } = await DAO.getFinancialAssessment()
if( get_financial_assessment ) {
const {
account_turnover,
cfd_score,
education_level,
employment_industry,
employment_status,
estimated_worth,
financial_information_score,
income_source,
net_income,
occupation,
source_of_wealth,
total_score,
trading_score,
} = get_financial_assessment;
this.setState(prevState => ({
anticipated_account_turnover: {...prevState.anticipated_account_turnover, value: account_turnover},
occupation: {...prevState.occupation, value: cfd_score},
level_of_education: {...prevState.level_of_education, value: education_level},
source_of_wealth: {...prevState.source_of_wealth, value: employment_industry},
net_annual_income: {...prevState.net_annual_income, value: employment_status},
estimated_net_worth: {...prevState.estimated_net_worth, value: estimated_worth},
source_of_wealth: {...prevState.source_of_wealth, value: financial_information_score},
}));
} else {
console.log('nope');
}
}
Any better way? One possible approach might be, once we get the data, we can make an object and setState
the object to the state. Would it be the best possible answer?
Solution
First things first, I am against using different names in things that are inherently the same. If you do not have any other option, you could the data coming from the DAO as soon as they are fetched from the server.
If that is not an option, since this code is indeed messy, I would move this logic into a function while indicating the mapping from one state to the other (this is similar to what Redux does with mapStateToProps).
const mapFinancialAssesmentToState = (fa, state) => {
const mapping = {
anticipated_account_turnover: fa.account_turnover,
occupation: fa.cfd_score
//...
};
const nextState = {};
Object.keys(mapping).forEach(key => {
nextState[key] = { ...state[key], value: mapping[key] };
})
return nextState;
}
async componentDidMount() {
let { get_financial_assessment } = await DAO.getFinancialAssessment();
if (get_financial_assessment) {
this.setState(mapFinancialAssesmentToState(get_financial_assessment, this.state))
} else {
console.log('nope');
}
}