как соединить или вставить новые элементы в конкретный индекс с помощью usestate?

Я пытаюсь вставить новые элементы в массив и обновить базу состояний в массиве, но проблема после обновления состояния. Он не отображается в компоненте.

  • примечание: я не совсем уверен, как использовать сращивание. (Я хотел, чтобы функция handleClick добавляла новый элемент под выбранным элементом, но, похоже, мне это тоже не удалось.)
  • примечание 2: я тоже пробовал setstate((pre) => { pre.splice(index + 1, 0, { id: 3, text: "xxx", autoFocus: true }); return pre; }); , но тоже не сработало.
import React, { useState } from "react";
import "./styles.css";

export default function App() {
  let elements = [
    { id: 0, text: "first", autoFocus: true },
    { id: 1, text: "second", autoFocus: true },
    { id: 2, text: "third", autoFocus: true }
  ];
  const [state, setstate] = useState(elements);

  function handChange(e) {
    if (e.keyCode == 13) {
      const x = state;
      const index = x.findIndex((item) => item.id == e.target.id);

      //i'm using autoFocus to move the focus  (I-beam pointer) to the nex field.
      //but i still get errors with it
      // e.map((item) => Object.assign(item, { autoFocus: false }));
      
      x.splice(index + 1, 0, { id: 3, text: "xxx", autoFocus: true });
      console.log(state); // you can see this update probarly
      setstate(x); // but when I update state sometimes it don't render othertimes it take a while before render.

    }
  }

  return (
    <div className="App">
      {state.map((e) => (
        // when I say it don't render I mean the e value don't get updated.
        <div
          focus={e.focus}
          contentEditable="true"
          id={e.id}
          onKeyUp={handChange}
        >
          {e.text}
        </div>
      ))}
    </div>
  );
}

на codeandbox


person ali al-karaawi    schedule 14.09.2020    source источник
comment
Как узнать, когда обновить элемент с каким индексом?   -  person Prateek Thapa    schedule 14.09.2020
comment
используя `const index = x.findIndex ((item) =› item.id == e.target.id); `   -  person ali al-karaawi    schedule 14.09.2020


Ответы (2)


Вы можете использовать splice для обновления вашего массива.

const newArray = [...state];
newArray.splice(e.target.id, 0, newElement);
setstate(newArray);

Поскольку splice изменяет исходный массив. Вы можете использовать оператор распространения, чтобы создать новый массив, а затем применить к нему сращивание.

Это создает новый массив с состоянием в нем.

[...state]

Вы можете проверить документы по монтажу здесь

person Prateek Thapa    schedule 14.09.2020
comment
не state = [... state], они должны быть точно такими же, и нет необходимости в ... - person ali al-karaawi; 14.09.2020
comment
Что ты имеешь в виду? - person Prateek Thapa; 14.09.2020
comment
вы можете просто написать это так const newArray =state.splice(e.target.id, 0, newElement); setstate(newArray) - person ali al-karaawi; 14.09.2020
comment
почему, splice не возвращает newArray, но редактирует массив. - person ali al-karaawi; 14.09.2020
comment
Моя беда, снова запуталась между splice и slice, обновил код. Спасибо за разъяснения. - person Prateek Thapa; 14.09.2020

Вместо использования

x.splice(index + 1, 0, { id: 3, text: "xxx", autoFocus: true });
      setstate(x)

Я заменяю его этим кодом

setstate((pre) => {
      
        return [
          ...pre.slice(0, index + 1),
          { id: 3, text: "xxx", autoFocus: true },
          ...pre.slice(index + 1, state.length)
        ];
      })

которые возвращают элементы перед элементом в индексе index + 1 + новый элемент + элементы после элемента в индексе index + 1

  • например, если у вас есть 3 элемента, и вы нажимаете Enter на 2-м элементе, тогда индекс будет 1, и вы создадите новый элемент в индексе 1+1, а после него вы вернете третий элемент, который находится в область между 1+1, 3, в которой 3 - длина массива.

альтернативное объяснение:

  • ...pre.slice(0, index + 1), это возвращает все элементы перед элементом, который вы нажали, введите в него + элемент, который вы нажали, введите в него.
  • { id: 3, text: "xxx", autoFocus: true }, это создаст новые элементы после предыдущих элементов
  • ...pre.slice(index + 1, state.length) это вернет элементы после элемента, на который вы нажали ввод (в случае отсутствия, он ничего не вернет)
person ali al-karaawi    schedule 14.09.2020
comment
Ответы только на код не приветствуются в Stack Overflow, потому что они не объясняют, как это решает проблему. Измените свой ответ, чтобы объяснить, что делает этот код и как он отвечает на вопрос, чтобы он был полезен другим пользователям с аналогичными проблемами. - person FluffyKitten; 15.09.2020