【问题标题】:Too Many Re Renders React JS - useState太多重新渲染 React JS - useState
【发布时间】:2020-02-25 16:20:44
【问题描述】:

我有一个映射的项目列表作为单选按钮。我正在切换选中状态。

我收到来自setCheckedState({i: false}); 的错误,导致重新渲染过多。

我将如何解决这个问题?

// 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>
    );
})}

【问题讨论】:

  • 渲染时不能设置状态,因为设置状态会导致重新渲染,从而导致死循环。使用useState 声明状态时设置状态的默认值
  • 这是有道理的,我试过了,但它最终会切换所有单选按钮,而不仅仅是点击的那个。

标签: reactjs loops babeljs


【解决方案1】:

正如 Jayce444 指出的那样,渲染中的setActive({i:false}); 会因为无限循环而给您带来麻烦。

顺便说一句,您错误地调用了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 here)


  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>
  )

【讨论】:

    【解决方案2】:

    试试这个代码

    // 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>
        );
    })}
    

    【讨论】:

      猜你喜欢
      • 2020-08-15
      • 2020-11-27
      • 1970-01-01
      • 2021-10-21
      • 2022-06-18
      • 2021-02-26
      • 2020-09-18
      • 2021-12-29
      • 1970-01-01
      相关资源
      最近更新 更多