Цель
Я обертываю список элементов сообщения с помощью компонента ListWrap. Этот компонент предназначен для обертывания каждого элемента в списке и определить, когда дочерние элементы добавляются или удаляются из списка. Он отображает все элементы, даже если они удалены из списка родительских компонентов, и просто меняет цвет оболочки на красный для удаленных или зеленый для добавленных.
У этого есть более важная цель, но для демонстрации проблема, я просто настраиваю цвет оболочки.
Проблема
Проблема, с которой я сталкиваюсь, заключается в том, что при удалении элементов которые не являются последним элементом в списке, также удаляются все последующие элементы. Так, например, из 3 элементов, если элемент 2 выбран для удаления, элементы 2 и 3 будут удалены.
Я не уверен, почему это происходит, потому что при удалении компонента ListWrap список функционирует. отлично. При использовании ListWrap и передаче дочерних элементов непосредственно в оператор возврата все работает нормально. Но когда я пытаюсь вернуть измененный набор детей, возникает проблема. Я заметил, что это напрямую влияет на состояние родительских сообщений, поэтому кажется, что некоторая логика в дочернем элементе приводит к удалению дополнительных элементов списка, даже если для удаления выбран только один.
Пример Codesandbox
Приведенный пример показывает, что при нажатии на кнопку закрытия/удаления элемента ожидаемое поведение должно только сделать эту оболочку красной (окрашенной слева). поле), а не все элементы ниже.
Test.js
import React, { useState } from "react";
import ListWrap from "./ListWrap";
const Test = () => {
const [messages, setMessages] = useState([]);
const addMessage = () => {
const id = Date.now();
setMessages([...messages, { id: id, text: `Message ${id}` }]);
};
const removeMessage = (id) => {
setMessages(messages.filter((message) => message.id !== id));
};
return (
Add New
setMessages(messages.slice(0, -1))}
className="rounded bg-orange-500 px-4 py-2 text-white hover:bg-orange-600 focus:outline-none"
>
Remove Last
setMessages([])}
className="rounded bg-red-500 px-4 py-2 text-white hover:bg-red-600 focus:outline-none"
>
Remove All
{messages.map((message) => (
{message.text}
removeMessage(message.id)}
className="absolute right-0 top-0 mr-2 mt-2 rounded bg-red-500 px-2 py-1 text-white hover:bg-red-600 focus:outline-none"
>
X
))}
);
};
export default Test;
ListWrap.js
import React, { useState, useEffect } from "react";
const ListWrap = ({ children }) => {
const [allChildrenItems, setAllChildrenItems] = useState([]);
useEffect(() => {
const newChildren = React.Children.toArray(children);
const newChildrenKeys = newChildren.map((child) => child.key);
const currentChildrenKeys = allChildrenItems.map((item) => item.child.key);
const addedChildrenKeys = newChildrenKeys.filter(
(key) => !currentChildrenKeys.includes(key)
);
const removedChildrenKeys = currentChildrenKeys.filter(
(key) => !newChildrenKeys.includes(key)
);
const updatedChildrenItems = [
...allChildrenItems.map((item) => {
if (removedChildrenKeys.includes(item.child.key))
return { ...item, isActive: false };
return item;
}),
...newChildren
.filter((child) => addedChildrenKeys.includes(child.key))
.map((child) => ({ child, isActive: true })),
];
setAllChildrenItems(updatedChildrenItems);
}, [children]);
//Using a custom item based on the children data IS causing issue with parent messages state:
return (
{allChildrenItems.map((item) => (
{item.child}
))}
);
//Using children directly from prop NOT causing issue with parent messages state:
// return (
//
// {children.map((item) => (
//
// {item}
//
// ))}
//
// );
// };
};
export default ListWrap;
Подробнее здесь: https://stackoverflow.com/questions/793 ... be-deleted
Дочерний компонент React приводит к удалению элементов родительского состояния ⇐ Javascript
-
- Похожие темы
- Ответы
- Просмотры
- Последнее сообщение