El valor de mi estado es

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

¿Cómo puedo usar la función javascript reduce() para cambiar el valor de line de tag1 y tag2 a "changed text"?

2
Hareesh 10 may. 2019 a las 15:44

4 respuestas

La mejor respuesta

Aquí estás:

this.setState(prevState => {
    return {
        content: {
            ...prevState.content,
            text: Object.keys(prevState.content.text).reduce((newTexts, key) => {
                return {
                    ...newTexts,
                    [key]: {
                        line: "changed text"
                    }
                }
            }, {})
        }
    }
});
1
Andrii Golubenko 10 may. 2019 a las 15:24

Debería setState con una función para no cambiar state directamente.

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

Editar:

No estoy seguro si cambiar prevState directamente es algo bueno (alguien me corrige), pero también puedes hacerlo

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

Editar:

Como se dijo en los comentarios, {...prevState} será una copia superficial y aún puede cambiar el estado directamente. Una solución para esto es usar lodash cloneDeep

1
Vencovsky 10 may. 2019 a las 14:56

Creo que usar for..in será mejor.

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)
0
Maheer Ali 10 may. 2019 a las 12:48

No creo que Array#prototype#reduce sería un ajuste.

Puede usar un bucle simple for...of moderno con Object.entries y haga esto:

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

Para lograr un estado inmutable, puede hacer {{ X0}} antes de mutar las propiedades del nuevo objeto.

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
Kunal Mukherjee 10 may. 2019 a las 12:59