Как я могу изменить состояние массивов с помощью хуков?

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

Единственное, что я нашел для работы, это использование useReducer для выполнения одного обновления массива с отправкой обработчиков onClick. В моем текущем проекте я пытаюсь обновить состояние массива в цикле for, вложенном в функцию, которая запускается при отправке формы. Я пробовал много разных решений, и это только одна из моих попыток.

  function sessionToState(session) {
    let formattedArray = []
    for (let i = 0; i < session.length; i++) {
      formattedArray.push({ url: session[i] })
      setLinksArray([...linksArray, formattedArray[i]])
    }
  }

  // --------------------------------------------------------

  return (
    <div>
      <form
        method = "post"
        onSubmit = {async e => {
          e.preventDefault()

          const session = await getURLs({ populate: true })

          sessionToState(session)

          await createGroup()

Мне было интересно, есть ли какие-то важные вещи, которые я упустил, или, может быть, несколько отличных советов и приемов о том, как работать с массивами с помощью хуков. Если нужна дополнительная информация, не стесняйтесь спрашивать. Спасибо.

Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
Улучшение производительности загрузки с помощью Google Tag Manager и атрибута Defer
В настоящее время производительность загрузки веб-сайта имеет решающее значение не только для удобства пользователей, но и для ранжирования в...
Безумие обратных вызовов в javascript [JS]
Безумие обратных вызовов в javascript [JS]
Здравствуйте! Юный падаван 🚀. Присоединяйся ко мне, чтобы разобраться в одной из самых запутанных концепций, когда вы начинаете изучать мир...
Система управления парковками с использованием HTML, CSS и JavaScript
Система управления парковками с использованием HTML, CSS и JavaScript
Веб-сайт по управлению парковками был создан с использованием HTML, CSS и JavaScript. Это простой сайт, ничего вычурного. Основная цель -...
JavaScript Вопросы с множественным выбором и ответы
JavaScript Вопросы с множественным выбором и ответы
Если вы ищете платформу, которая предоставляет вам бесплатный тест JavaScript MCQ (Multiple Choice Questions With Answers) для оценки ваших знаний,...
0
0
1 795
3
Перейти к ответу Данный вопрос помечен как решенный

Ответы 3

При вызове установщика состояния из вызовов вложенных функций вы должны использовать функциональная форма обновления setState. В вашем случае это будет:

setLinksArray(linksArray => [...linksArray, formattedArray[i]])

Не совсем понятно, с какими проблемами вы столкнулись, но указанное выше исправление спасет вас от неожиданного состояния linksArray.

Также это относится к любому состоянию, а не только к массивам.

С точки зрения производительности вы не должны вызывать setState каждую итерацию. Вы должны установить состояние с окончательным массивом.

const sessionToState = (session) => {
  setLinksArray(
   session.map(sessionItem => ({url: sessionItem}))
  );
}

... или если вы хотите сохранить старые элементы, вы должны сделать это с помощью функции внутри setState ...

const sessionToState = (session) => {
  setLinksArray(oldState => [
   ...oldState,
   ...session.map(sessionItem => ({url: sessionItem}))
  ]);
}

Спасибо за ответ. В итоге я использовал useReducer для проверки некоторых вещей и понял, что, похоже, есть проблемы с редактированием состояния onSubmit. Как мне отложить отправку до тех пор, пока состояние не будет обновлено, или есть другая стратегия? Прямо сейчас я тестирую его, имея отдельную кнопку для выполнения обновления состояния, а затем, когда я нажимаю кнопку «Отправить», состояние корректно при отправке на сервер.

ElektrikSpark 08.04.2019 10:09
Ответ принят как подходящий

I was wondering if there are any big things that I am missing

TLDR: setLinksArray обновляет linksArray не в текущем рендере, а в следующем рендере.


Предположим, что переменные инициализированы следующим образом:

const [linksArray, setLinksArray] = useState([])

Подсказка в ключевом слове const, linksArray — это постоянный в пределах 1 рендера (и этот факт не изменится с let, потому что именно так работает useState).

Идея setLinksArray() состоит в том, чтобы сделать другое постоянное значение в следующем рендере.

Таким образом, цикл for будет похож на:

setLinksArray([...[], session0])
setLinksArray([...[], session1])
setLinksArray([...[], session2])

и вы получите linksArray = [session2] в следующем рендере.

Лучший способ оставаться в здравом уме — это вызывать любую функцию setState только один раз для каждого состояния при каждом рендеринге (хотя у вас может быть несколько состояний), наименьшее изменение в вашем коде:

function sessionToState(session) {
  let formattedArray = []
  for (let i = 0; i < session.length; i++) {
    formattedArray.push({ url: session[i] })
  }
  setLinksArray(formattedArray)
}

Кроме того, если вам нужно выполнить побочный эффект (например, вызов API) после того, как все setState функции сделают свою работу, то есть после СЛЕДУЮЩЕГО рендеринга, вам понадобится useEffect:

useEffect(() => {
    ...do something with updated linksArray...
}, [linksArray])

Для более подробного ознакомления см. https://overreacted.io/react-as-a-ui-runtime

Теперь я гораздо яснее понимаю, что происходит за кулисами, что, как мне кажется, доставляет мне больше всего проблем. Спасибо за ответ.

ElektrikSpark 09.04.2019 01:55

Другие вопросы по теме