#javascript #arrays #reactjs #use-state
Вопрос:
Я не могу удалить определенные элементы массива по номеру индекса из любого динамического div
const { useState } = React;
function Check(){
var [Children, setChildren] = useState([])
function RemArr(docs){
const temp = [...Children]
temp.splice(docs["i"], 1);
setChildren(temp)
}
function Product(docs) {
var document = (<React.Fragment>
<button onClick={()=>RemArr(docs)}>
List {docs["i"]}
</button>
<p></p>
<input/>
<p></p>
</React.Fragment>);
setChildren([...Children, document])
}
return (<React.Fragment>
<div>Check</div>
{Children}
<button
onClick={()=>{Product({fix:false, i:Children.length})}}
>Add List </button>
</React.Fragment>)
}
ReactDOM.render(<Check />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>
Когда я хочу удалить какой-либо конкретный div, то не только этот div удаляют из массива, но и удаляют следующий div из массива.
Напр..
array = [0,1,2,3,4,5,6,7,8,9]
Однако, если я хочу удалить только 6
из массива, вместо этого он удаляет все значения из 6
to 9
, и поэтому у меня остается только:
array = [0,1,2,3,4,5]
Я думаю, что проблема возникает из-за этой функции:
function RemArr(docs){
const temp = [...Children]
temp.splice(docs["i"], 1);
setChildren(temp)
}
Ответ №1:
Ваша RemArr
функция имеет закрытие Children
, что означает , что нажатие на кнопку удалить вызовет потенциально старое объявление remArr
, в котором remArr
Children
массив будет ссылаться на состояние дочернего массива с момента первоначального добавления обработчика события щелчка, а не на текущее состояние Children
.
Чтобы преодолеть это, вы можете разбить его Product
на компоненты, а не превращать в функцию , и ввести Children
в него состояние, основанное на некотором состоянии Choice
, которое вы можете использовать для создания элементов вашего продукта:
const {useState} = React;
function Product({docs, onClick}){
return <React.Fragment>
<button onClick={onClick}>
List {docs.i}
</button>
<p></p>
<input/>
<p></p>
</React.Fragment>;
}
function Check() {
const [products, setProducts] = useState([]);
function remArr(index){
const temp = [...products];
temp.splice(index, 1);
setProducts(temp);
}
function addProduct() {
const prevNum = products[products.length-1];
setProducts([...products, {
fix: false,
i: prevNum === undefined ? 0 : prevNum.i 1
}]);
}
return (<React.Fragment>
<div>Check</div>
{products.map(
(doc, i) => <Product key={doc.i} docs={doc} onClick={() => remArr(i)}/>
)}
<button
onClick={addProduct}
>Add List</button>
</React.Fragment>);
}
ReactDOM.render(<Check />, document.body);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.0/umd/react-dom.production.min.js"></script>
Описанный выше .map()
метод, который создает новые <Product />
компоненты, «обновляет»/переопределяет onClick
функцию всех компонентов продукта, указывая на «последнюю» объявленную remArr
функцию, которая имеет доступ к правильному/актуальному products
массиву. Это не похоже на ваш пример, где старые объекты JSX внутри Children
массива все еще имеют onClick
атрибуты, которые ссылаются на старые объявления remArr
функции (которые имеют доступ к старому Children
состоянию массива).
Комментарии:
1. Я все еще не понимаю этого. В оперативном коде ремАрр имеет доступ к старым детям. Но разве не должно быть так и здесь, у remArr должен быть доступ к массиву старых продуктов?
2. @TusharShahi
.map()
, который создает новые<Product />
компоненты, «обновляет»onClick
функцию всех компонентов, чтобы указать на «последнюю» объявленнуюremArr
функцию, которая имеет доступ к правильному/обновленномуproducts
массиву. В то время как в коде OPs старые объекты JSX внутри дочернего массива все еще имеютonClick
атрибуты, которые ссылаются на старые объявленияremArr
функции (которые имеют доступ к старомуChildren
состоянию массива).3. Эй, Ник Парсонс, Ваш код работает, но не полностью, потому что, если я удалю список 4 или любой другой, то он удалит номер 4, но мой ввод не удален из поля с номером 4.При нажатии для удаления всегда удаляется последний ввод. amp; Также мне нужно инициализировать функцию продукта внутри основной функции (Проверка), потому что мне нужно использовать useState, которое определено в функции проверки. Итак, как использовать функцию продукта внутри функции проверки? Пожалуйста. amp; Я использую следующий js
4. @MunnyReol привет, я обновил
key
опору, чтобы устранить проблему с вводом. С точки зрения инициализации продукта внутри проверки, это никогда не должно быть сделано. Вы можете поддерживать свое состояние под контролем, а затем передавать методы (такие как setProducs) в компонент продукта с помощью реквизитов, которые позволят вам обновить состояние вашего компонента проверки внутри продукта5. @MunnyReol вы можете изменить
i
, чтобы он основывался на номере предыдущего элемента списка плюс 1. Я обновил фрагмент.