【问题标题】:getting infinite loop error while setting useState() ReactJs设置useState()ReactJs时出现无限循环错误
【发布时间】:2022-01-27 23:16:49
【问题描述】:

我有 mutliSelect,我的情况是: 当 Value 属性为 [] 时(multiSelect 组件获取此属性),将我的 useState 也设置为 []。

我试着写这样的东西:

const [selected, setSelected] = useState([]);

useEffect(() => {
  setSelected([]);
}, [Value]);

<Select
  style={style}
  maxTagCount={0}
  maxTagPlaceholder={maxTagPlaceholder}
  mode="multiple"
  placeholder={placeholder}
  showSearch

  value={selected} // here I tried to put the Value but not working well

  onSelect={(val) => onSelectValueMultiSelect(val, selected, setSelected, options)}
  onDeselect={(val) => onDeselectValueMultiSelect(val, selected, setSelected)}>
  {childrenOptions}
</Select>

但我得到了无限循环错误。

Value 数组包含数组形式的过滤器数据,单击“重置过滤器”按钮我想重置我的 multiSelect 字段。

我认为问题在于当 setSelected([]) 调用它时,它会再次渲染 Value,因此 useEffect 会一次又一次地调用。

我的 MultiSelect 组件:

import React, { useEffect, useState } from 'react';
import './MultiSelect.scss';

import { maxTagPlaceholder, onSelectValueMultiSelect, onDeselectValueMultiSelect } from '../Services';
import { Select, Checkbox } from 'antd';

const MultiSelect = ({ options, style, onChangeHandle, placeholder, Value }) => {
  const [selected, setSelected] = useState([]);
  const [childrenOptions, setChildrenOptions] = useState([]);
  const { Option } = Select;
  const children = [];

  useEffect(() => {
    options.forEach((option) => {
      children.push(
        <>
          <Option key={option.value}>
            <Checkbox className="multi-select-checkbox" checked={selected.some((x) => x === option.value)} />
            {option.value}
          </Option>
        </>
      );
    });
    setChildrenOptions(children);
  }, [selected]);

useEffect(() => {
  onChangeHandle(selected);
}, [selected]);

useEffect(() => {
  setSelected([]);
}, [Value]);

  return (
    <Select
      style={style}
      maxTagCount={0}
      maxTagPlaceholder={maxTagPlaceholder}
      mode="multiple"
      placeholder={placeholder}
      showSearch
      value={selected}
      onSelect={(val) => onSelectValueMultiSelect(val, selected, setSelected, options)}
      onDeselect={(val) => onDeselectValueMultiSelect(val, selected, setSelected)}>
      {childrenOptions}
    </Select>
  );
};

export default MultiSelect;

【问题讨论】:

  • 能否提供完整的组件?就像你说的,设置状态会导致重新渲染,这可能是问题所在。

标签: javascript html reactjs react-hooks antd


【解决方案1】:

如果Value 是根据selected 计算的,那么这个useEffect() 就是问题所在:

useEffect(() => {
  setSelected([]);
}, [Value]);

正如你所说,它会导致无限循环,因为selected 一次又一次地变化,导致Value 也发生变化并且组件不断重新渲染。

另一个查找错误的地方是在带有onSelect 和onDeselect 的&lt;Select&gt; 组件回调中。在大多数情况下,将setSelected 作为参数传递并不是一个好主意,因为useState hook has side effects。您在这里没有提供完整的代码,但我认为这也可能会导致组件中的状态变化不稳定并导致重新渲染。

此外,您有 2 个 useEffect() 都具有 [selected] 作为依赖项,因此当 selected 更改时,它也会导致组件重复渲染。但是,这不是您的主要问题的原因。

解决方案只能使用 1 个useEffect(),如下所示:

第 1 步。关于您的 &lt;Select&gt; 组件回调:

onSelect={handleSelect}
onDeselect={handleDeselect}

const handleSelect = (val) => {
  // think about removing setSelected
  onSelectValueMultiSelect(val, selected, setSelected, options);
  // move this here
  onChangeHandle(selected);
  // reset selected here if wanted
  setSelected([]);
}

const handleDeselect = (val) => {
  // think about removing setSelected
  onDeselectValueMultiSelect(val, selected, setSelected, options);
  // move this here
  onChangeHandle(selected);
  // reset selected here if wanted
  setSelected([]);
}

第 2 步。重构您的 useEffect(),仅使用 1 而不是 3:

useEffect(() => {
  options.forEach(...);
  setChildrenOptions(children);
}, [selected]);

这不是最干净的代码,但这可能是解决您非常特殊的问题的正确方向,而无需对其余代码了解太多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-03-31
    • 2020-12-14
    • 2022-11-11
    • 1970-01-01
    • 2021-08-11
    • 2021-11-11
    • 1970-01-01
    相关资源
    最近更新 更多