javascript - manejo - Redux-Eliminar el objeto de la matriz anidada en otra matriz
manejo de array con javascript (2)
La actualización de una estructura anidada puede ser muy desagradable en redux. Sugiero usar una estructura más plana. Puedes hacer esto usando el normalizador o manualmente.
Sin embargo, si necesita actualizar su estructura existente, estos son los pasos:
- Encuentra el índice del comentario que deseas cambiar.
- Crea una nueva matriz de respuestas filtradas para el comentario.
- Cree una nueva matriz de datos reemplazando el comentario anterior con un nuevo comentario que contenga la nueva matriz de respuestas.
- Crea un nuevo objeto de estado con una nueva matriz de datos.
Ejemplo
const state = {"count":4,"data":[{"id":123,"text":"This is a comment","replies":[{"id":479,"text":"This is a reply"},{"id":293,"text":"This is another reply"}]},{"id":728,"text":"This is another comment","replies":[{"id":986,"text":"This is a reply"}]}],"pageSize":5,"cursor":""};
const action = {
parentCommentId: 123,
replyId: 479
};
const deleteReplySuccess = () => {
const data = state.data;
// find the index of the comment you want to update
const commentToChangeIndex = data.findIndex(({ id }) => id === action.parentCommentId);
// if it doesn''t exist return the state
if(commentToChangeIndex === -1) {
return state;
}
// get the comment
const comment = data[commentToChangeIndex];
// create an updated comment with filtered replies array
const updatedComment = {
... comment,
replies: comment.replies.filter(reply => reply.id !== action.replyId)
};
// create a new state using object spread or assign
return {
...state,
data: [ // create a new data array
...data.slice(0, commentToChangeIndex), // the comments before the updated comment
updatedComment, // the updated comment
...data.slice(commentToChangeIndex + 1) // the comments after the updated comment
]
};
};
console.log(deleteReplySuccess());
Mi estado de Redux almacena un objeto de comments
que almacena una serie de comentarios. Cada objeto de comment
tiene una matriz de replies
en él. Estoy pasando tanto el ID de comentario principal como el ID de respuesta a mi reductor con la intención de eliminar la respuesta de la matriz de respuestas.
Una versión simplificada de mi objeto de comentarios de nivel superior se ve así:
{
"count": 4,
"data": [
{
id: 123,
text: ''This is a comment'',
replies: [
{
id: 479,
text: ''This is a reply'',
},
{
id: 293,
text: ''This is another reply'',
},
],
},
{
id: 728,
text: ''This is another comment'',
replies: [
{
id: 986,
text: ''This is a reply'',
},
],
},
],
"pageSize": 5,
cursor: "",
}
Y aquí está mi reductor que parece envolver el objeto de comentario principal en una matriz y aplanar las respuestas (obviamente no es el resultado deseado, pero estoy perdido en cuanto a la mejor manera de abordar la matriz anidada).
case types.DELETE_REPLY_SUCCESS: {
const content = Object.assign({}, state);
content.data = content.data.map((comment) => {
const newObj = { ...comment };
if (newObj.id === action.parentCommentId) {
return newObj.replies.filter(reply => reply.id !== action.replyId);
}
return newObj;
});
return content;
}
La respuesta anterior es más directa, pero quería compartir algunos de mis pensamientos.
En primer lugar, este enlace sobre el estado de normalización en Redux resolvió lo que era un gran problema para mí ... tratar con estructuras de datos anidados ... su código se vuelve muy complejo. El 90% de tus reductores debería ser sorprendentemente simple. Y con estructuras de datos anidados se vuelven complejos .
Aunque el normalizador es una herramienta bastante estándar para normalizar el estado, recomiendo escribir el suyo al principio. Aprendí mucho de hacerlo de esa manera.
¿Qué es una estructura de datos normalizada?
Es plano Y es típicamente relacional.
Dan Abramov (quien construyó Redux), sugiere almacenar datos agrupados. Entonces tus comentarios se convierten en un grupo y tus respuestas comparten otro. Al igual que en una base de datos relacional. Cada "grupo" tiene su propia "mesa".
Al principio, esto me pareció contrario a la intuición porque parece que estás escribiendo más estructura de datos. No lo eres ... y las recompensas valen la pena.
Entonces almacenarías tus datos algo así
{
"comments": {
"allIds" : [1,2,3,4],
"byId": {
1: {
replies: [12],
comment: "a comment"
},
2: {
replies: [13],
comment: "another comment"
},
3: {
replies: [14],
comment: "one more comment"
},
4: {
replies: [15],
comment: "oh look, a comment"
},
}
},
"replies" : {
"allIds" : [12,13,14,15],
"byId": {
12: {
comments: [1],
reply: "a reply"
},
13: {
comments: [2],
reply: "another reply"
},
14: {
comments: [3],
reply: "yet another reply"
},
15: {
comments: [4],
reply: "a reply"
}
}
}
¿Por qué es tan importante?
¿De qué manera esto hace la vida más fácil? Bueno, en primer lugar, si alguna vez queremos mostrar una lista de comentarios, podemos simplemente map()
través de nuestra matriz allIds
y usar el primer parámetro para acceder a la clave para acceder a los datos.
Esto significa que podemos iterar a través de una sola matriz en lugar de a través de un objeto anidado.
De la misma manera, y en respuesta a su pregunta , puede eliminar un elemento utilizando filter()
lugar de map()
. No me molestaré en explicar el filtro aquí. Tardan diez segundos en encontrar ejemplos que son mejores que cualquier cosa que pueda explicar.
Luego solo asegúrate de haber seguido la forma estándar de hacer las cosas en Redux.
Replica tu estructura de datos usando reductores. Su estado debe iniciarse sin datos ... de esa manera usted sabe que lo ha hecho bien.
Escriba sus reductores que manejan su estado específico (comentarios reductor, etc.) Para mí, estos normalmente consisten en declaraciones de cambio que devuelven el estado o devuelven un nuevo estado.
Escriba acciones que le proporcionen a un reductor los nuevos datos que necesita. Siempre siga el principio JS de tener una función para manejar un trabajo. Las acciones no deberían hacer muchas cosas.
NOTA: sin embargo, al usar middleware como thunk, las acciones pueden enviar otras acciones que pueden dar como resultado una maravilla lógica.
una acción de eliminación para un comentario puede parecer algo tan simple como
function deleteComment(commentId) {
return {
type: "delete project",
payload: commentId
}
}
Esto nos da todo lo que necesitamos. Al usar la declaración de cambio mencionada anteriormente en nuestro reductor, podemos verificar qué type
de acción se está enviando. (esto nos dice qué hacer con los datos suministrados) y qué elemento eliminar, es decir, la carga útil.
Puede seguir este enfoque simple para el 85% de las necesidades de su aplicación.
Entiendo que hay mucho más en Redux que este, pero este enfoque realmente me ayudó a entender cómo ver Redux y cómo administrar y manipular el estado. Recomiendo encarecidamente revisar el tutorial completo de eggheads.io por Dan Abramov vinculado anteriormente. Hace un gran trabajo al explicar casi todo en detalle.
Espero que esta larga respuesta a tu breve pregunta ayude.