реагировать крючки useState Array - PullRequest
0 голосов
/ 18 декабря 2018

Я попытался сбросить здесь значения массива useState, но не смог найти никаких ссылок на значения массива.

Попытка изменить раскрывающееся значение из исходного состояния в значения allowState.Я использую метод ловушек здесь, чтобы установить значения, используя - setStateValues.Если я прокомментирую эту строку кода, она отобразит раскрывающийся список.Я не мог понять, почему я не могу использовать метод setStateValues ​​для сброса значений переменных состояния.

Я получаю следующую ошибку: «Слишком много повторных визуализаций. React ограничивает число визуализаций, чтобы предотвратить бесконечный цикл».

Пожалуйста, помогите, если вы видите здесь что-то не так.Я буду продолжать искать.

    import React, { useState } from "react"; 
    import ReactDOM from "react-dom";

    const StateSelector = () => {   
    const initialValue = [
    { id: 0,value: " --- Select a State ---" }];

      const allowedState = [
        { id: 1, value: "Alabama" },
        { id: 2, value: "Georgia" },
        { id: 3, value: "Tennessee" }
        ];

      const [stateOptions, setStateValues] = useState(initialValue);  
      // initialValue.push(...allowedState);

      console.log(initialValue.length);

      setStateValues(allowedState); // Not sure why cannot I reset the state in here for an array.

         return (<div>
          <label>Select a State:</label>
          <select>
            {stateOptions.map((localState, index) => (
              <option key={localState.id}>{localState.value}</option>
            ))}
          </select>
        </div>   ); };

    const rootElement = document.getElementById("root");
    ReactDOM.render(<StateSelector />, rootElement);

Ответы [ 4 ]

0 голосов
/ 23 июня 2019

Чтобы раскрыть ответ Райана:

При каждом вызове setStateValues ​​React выполняет рендеринг вашего компонента, что означает, что тело функции функции компонента StateSelector выполняется повторно.

Реакция документы :

setState () всегда будет приводить к повторному рендерингу, если shouldComponentUpdate () не возвращает false.

По сути, вы устанавливаете состояние с помощью:

setStateValues(allowedState);

, что вызывает повторный рендеринг, который затем приводит к выполнению функции, и так далее, и так далее.Это вызывает проблему цикла.

Чтобы проиллюстрировать точку, если вы установите тайм-аут как:

     setTimeout(
    () => setStateValues(allowedState),
    1000
  )

Это завершит проблему «слишком много повторных рендеров».

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

0 голосов
/ 22 июня 2019

Постарайтесь, чтобы ваше состояние было минимальным.Нет необходимости хранить

   const initialValue = [
    { id: 0,value: " --- Select a State ---" }];

как состояние.Отделите перманент от изменяющегося

const ALL_STATE_VALS = [
    { id: 0,value: " --- Select a State ---" }
    { id: 1, value: "Alabama" },
    { id: 2, value: "Georgia" },
    { id: 3, value: "Tennessee" }
];

Тогда вы можете сохранить только идентификатор в качестве вашего состояния:

const StateSelector = () =>{
  const [selectedStateOption, setselectedStateOption] = useState(0);

  return (
    <div>
      <label>Select a State:</label>
      <select>
        {ALL_STATE_VALS.map((option, index) => (
          <option key={option.id} selected={index===selectedStateOption}>{option.value}</option>
        ))}
      </select>
    </div>);
   )
}
0 голосов
/ 22 июня 2019

Принятый ответ показывает правильный способ setState, но не приводит к правильному функционированию поля выбора.

import React, { useState } from "react"; 
import ReactDOM from "react-dom";

const initialValue = { id: 0,value: " --- Select a State ---" };

const options = [
    { id: 1, value: "Alabama" },
    { id: 2, value: "Georgia" },
    { id: 3, value: "Tennessee" }
];

const StateSelector = () => {   
   const [ selected, setSelected ] = useState(initialValue);  

     return (
       <div>
          <label>Select a State:</label>
          <select value={selected}>
            {selected === initialValue && 
                <option disabled value={initialValue}>{initialValue.value}</option>}
            {options.map((localState, index) => (
               <option key={localState.id} value={localState}>
                   {localState.value}
               </option>
             ))}
          </select>
        </div>
      ); 
};

const rootElement = document.getElementById("root");
ReactDOM.render(<StateSelector />, rootElement);
0 голосов
/ 18 декабря 2018

Вы не должны устанавливать состояние (или делать что-либо еще с побочными эффектами) из функции рендеринга.При использовании хуков вы можете использовать useEffect для этого.

Следующая версия работает:

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";

const StateSelector = () => {
  const initialValue = [
    { id: 0, value: " --- Select a State ---" }];

  const allowedState = [
    { id: 1, value: "Alabama" },
    { id: 2, value: "Georgia" },
    { id: 3, value: "Tennessee" }
  ];

  const [stateOptions, setStateValues] = useState(initialValue);
  // initialValue.push(...allowedState);

  console.log(initialValue.length);
  // ****** BEGINNING OF CHANGE ******
  useEffect(() => {
    // Should not ever set state during rendering, so do this in useEffect instead.
    setStateValues(allowedState);
  }, []);
  // ****** END OF CHANGE ******

  return (<div>
    <label>Select a State:</label>
    <select>
      {stateOptions.map((localState, index) => (
        <option key={localState.id}>{localState.value}</option>
      ))}
    </select>
  </div>);
};

const rootElement = document.getElementById("root");
ReactDOM.render(<StateSelector />, rootElement);

и здесь она находится в песочнице кода .

Я предполагаю, что вы хотите в конечном итоге загрузить список состояний из некоторого динамического источника (в противном случае вы можете просто использовать allowedState напрямую, без использования useState вообще).Если это так, то вызов API для загрузки списка также может идти внутри блока useEffect.

...