Too Many Re Renders React JS - useState - PullRequest
0 голосов
/ 25 февраля 2020

У меня есть отображенный список элементов в виде переключателей. Я переключаю проверенное состояние.

Я получаю ошибку от setCheckedState({i: false});, вызывающую слишком много повторных рендеров.

Как мне go исправить это?

// Import useState
import { useState } from 'react';

// Set your active and SetActive items
const [active, setActive] = useState({});

{Object.values(equipment).map((item, i) => {
    // Defautl the item to non active
    setActive({i:false});
    return (
        <IonItem key={item}>
            <IonLabel>{item}</IonLabel>
            <IonRadio mode="md" slot="start" value={item} checked={active.i} onClick={() => {
                // Set the specific Item to active
                setActive({i:!active.i});
            }} />
        </IonItem>
    );
})}

Ответы [ 2 ]

1 голос
/ 25 февраля 2020

Как указывал Jayce444, setActive({i:false}); в рендере вызовет у вас проблемы из-за бесконечного l oop.

Как бы то ни было, вы неправильно набираете setActive. Вызов setActive({i:!active.i}) полностью перезапишет объект состояния в виде одной пары ключ / значение. Пример:

Допустим, вы начинаете с

active = {1: true, 2: false}
 // then you call
setActive({2:!active.2}) // now active looks like {2:!false} = {2: true}
// then you call
setActive({1:!active.1}) // now active looks like {1:!undefined} = {1: true}
// in this case you just happen to be getting lucky because
// all <IonRadio ... checked={active.i} ../> (other than your current set i)
// are evaluating to checked={undefined} which is the same as unchecked

. Вам не хватает скопировать существующее состояние перед обновлением конкретного ключа. Таким образом, собрать все вместе здесь возможно ( CodeSandbox здесь )


  const [active, setActive] = useState({});

  const [oneOnly, setOneOnly] = useState("");

  return (
    <div className="App">
      <h3>If you want to have multiple selections</h3>
      {Object.values(equipment).map((item, i) => (
        <label>
          <input
            key={item+"multi"}
            type="radio"
            value={item+"multi"}
            checked={active[item] || false}
            onClick={e => {
              setActive({ ...active, [item]: !active[item] });
            }}
          />
          {i}) {item}
          <br />
        </label>
      ))}
      <h3>... Or just one</h3>
      {Object.values(equipment).map((item, i) => (
        <label>
          <input
            key={item + "single"}
            type="radio"
            value={item + "single"}
            checked={oneOnly === item}
            onClick={e => {
              setOneOnly(item);
            }}
          />
          {i}) {item}
          <br />
        </label>
      ))}
    </div>
  )
0 голосов
/ 25 февраля 2020

попробуйте этот код

// Import useState
import { useState } from 'react';

// Set your active and SetActive items
const [active, setActive] = useState({});

{Object.values(equipment).map((item, i) => {
    // Defautl the item to non active
    setActive(prev => {...prev, [i]: false});
    return (
        <IonItem key={item}>
            <IonLabel>{item}</IonLabel>
            <IonRadio mode="md" slot="start" value={item} checked={active[i]} onClick={() => {
                // Set the specific Item to active
                setActive(prev => {...prev, [i]:!prev[i]});
            }} />
        </IonItem>
    );
})}
...