У меня есть приложение ReactJS, в одном компоненте у меня есть таблица, и я создаю каждую строку таблицы, используя метод map () в представлении компонентов (JSX), где каждая отдельная строка имеет кнопку-дубликат, чтобы пользователь мог дублировать строку и видеть ее под элемент, на который они нажали. например: если пользователь нажимает кнопку дублирования второй строки, я хочу клонировать индекс 1 массива данных страницы и обновить представление компонента на основе нового массива.
вот упрощенный код:
import React, {useState} from 'react';
const MyComponent = () => {
const [PageData, setPageData] = useState([
{name: "item1", id: "1"},
{name: "item2", id: "2"},
{name: "item3", id: "3"}
])
const duplicateItem = (RowItem, i) => {
let RowsData = [...PageData];
let Index = parseInt(i + 1);
RowsData.splice(Index, 0, Duplicate);
setPageData(RowsData);
}
return (
<div>
{PageData.map((Item, i) =>(
<div className = "form-row" key = {i}>
<p>{Item.name}</p>
<button
onClick = {() => duplicateItem(Item, i)}
className = "duplicate"
>
</button>
</div>
))}
</div>
)
}
export default MyComponent;
что мы ожидаем, так это то, что когда пользователь нажимает кнопку дублирования, строка добавляется под элементом, на который нажал пользователь (если они дублируют второй элемент, его дубликат появится под вторым элементом), я не Я не знаю, почему этот код не работает, и сегодня мой крайний срок, поэтому мне нужна помощь.
да это называется, но почему?



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете сделать это, как показано ниже.
Для простоты я использовал длину массива для обновления id вновь добавленного дублированного элемента. Кроме того, в duplicateItem вы уже получаете элемент для копирования, поэтому мы можем использовать его для добавления под выбранным элементом.
const {useState} = React;
const MyComponent = () => {
const [PageData, setPageData] = useState([
{name: "item1", id: "1"},
{name: "item2", id: "2"},
{name: "item3", id: "3"}
])
const duplicateItem = (RowItem, i) => {
setPageData(data => {
let RowsData = [...data];
//Create a new ID, for simplicity I'm just using the length of the array
const id = `${RowsData.length + 1}`;
//Add the same item with new id below the selected item
const Index = parseInt(i + 1);
RowsData.splice(Index, 0, {...RowItem, id});
return RowsData;
});
}
return (
<div>
{PageData.map((Item, i) =>(
<div className = "form-row" key = {i}>
<p>{Item.name}_{Item.id}</p>
<button
onClick = {() => duplicateItem(Item, i)}
className = "duplicate"
>
</button>
</div>
))}
</div>
)
}
ReactDOM.render(<MyComponent />, document.getElementById("react"));<script src = "https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src = "https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id = "react"></div>Спасибо за отличный отклик, этот метод работает отлично. Что, если у меня есть еще несколько свойств, которые я хочу добавить помимо id? как статус (логическое значение) или элемент выбора, который пользователь может изменять и дублировать с новыми значениями? Можно ли это сделать с помощью того же подхода?
Да, вы можете добавить столько свойств, сколько захотите. Подобно тому, как мы добавляли новый id, если вы хотите иметь значение по умолчанию для status, например false, вы можете добавить его или предоставить пользователю возможность выбрать status и использовать то же самое.
Но перед дублированием, если вы измените значение, это значение также будет обновлено до исходного значения. Один из способов - скопировать тот же объект и предоставить возможность изменить значение после того, как дублированный элемент будет добавлен в список.
Обратите внимание, я получаю неправильную строку, а дублированный элемент добавляется в конец списка, а не в нужный мне индекс.
Так ли это, но когда я проверил, все работает как положено. Чтобы избежать такой путаницы, я обновил ответ, добавив id к имени элемента списка в рендере при отображении. Пожалуйста, проверьте один раз.
да, у меня была еще одна ошибка в моем пользовательском интерфейсе, которая вызвала проблему. Ваше решение отлично работает, спасибо!
Если поставить точку останова в duplicateItem, она будет вызвана? Что происходит, когда вы переступаете через это?