Как использовать функцию Reduce во вложенном объекте состояния в ReactionJS? - PullRequest
2 голосов
/ 10 мая 2019

Мое значение состояния

this.state = {
    content: {
        text: {
            tag1: {
                line: "data1"
            }
            tag2: {
                line: "data2"
            }
        }
    }
}

Как я могу использовать функцию javascript reduce(), чтобы изменить значение line обоих tag1 и tag2 на "changed text"?

Ответы [ 4 ]

1 голос
/ 10 мая 2019

Вот вы:

this.setState(prevState => {
    return {
        content: {
            ...prevState.content,
            text: Object.keys(prevState.content.text).reduce((newTexts, key) => {
                return {
                    ...newTexts,
                    [key]: {
                        line: "changed text"
                    }
                }
            }, {})
        }
    }
});
1 голос
/ 10 мая 2019

Вы должны setState с функцией, чтобы вы не изменяли state напрямую.

this.setState(prevState => {        
    for(let k in prevState.content.text){
        prevState.content.text[k].line = "changed";
    } 
    return {content: prevState.content}
}

Редактировать:

Я не уверен, что изменить prevStateНепосредственно это хорошая вещь (пожалуйста, кто-нибудь поправьте меня), но вы также можете сделать

this.setState(prevState => {   
    let changedState = {...prevState}     
    for(let k in changedState.content.text){
        changedState.content.text[k].line = "changed";
    } 
    return {content: changedState.content}
}

Редактировать:

Как сказано в комментариях, {...prevState} будет поверхностнымскопировать и он все еще может изменить состояние напрямую.Одним из решений этой проблемы является использование lodash cloneDeep

0 голосов
/ 10 мая 2019

Не думаю, что Array#prototype#reduce подойдет.

Вы можете использовать простой современный цикл for...of с Object.entries и сделать это:

const state = {
    content: {
        text: {
            tag1: {
                line: "data1"
            },
            tag2: {
                line: "data2"
            }
        }
    }
};

for (const obj of Object.entries(state.content.text)) {
	obj[1].line = 'Changed text';
}

console.log(state);

Для достижения неизменного состояния вы можете сделать Object.assign перед изменением свойств нового объекта.

const state = {
  content: {
    text: {
      tag1: {
        line: "data1"
      },
      tag2: {
        line: "data2"
      }
    }
  }
};

// Create a new object from an existing object
const newState = Object.assign(state, {});

Object.entries(newState.content.text).forEach(x => {
  x[1].line = 'Changed text';
});

console.log(newState);
0 голосов
/ 10 мая 2019

Я думаю, что использование for..in будет лучше.

const state = {
    content: {
        text: {
            tag1: {
                line: "data1"
            },
            tag2: {
                line: "data2"
            }
        }
    }
}

for(let k in state.content.text){
  state.content.text[k].line = "changed";
} 
console.log(state)
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...