繁体   English   中英

React useEffect 导致函数运行 7 次。 我正在使用 useCallback 但它仍然运行很多次

[英]React useEffect causing function to run 7 times. I am using a useCallback but it still runs to many times

带有 console.log("running") 的 updateAddedState 函数在页面刷新/初始渲染中运行了 7 次。

我只希望 updateAddedState 函数在 addedItems 状态更新时运行一次。

我只在实际 addedItems 状态发生变化时运行 useEffect 。 我究竟做错了什么??

export const DropdownMultiSelect = ({
  data,
  placeholder,
  updateState,
}: IProps) => {
  const [searchTerm, setSearchTerm] = useState<string>("");
  const [filteredData, setFilteredData] = useState<IData[]>(data);
  const [addedItems, setAddedItems] = useState<IData[]>([]);
  const [placeholderValue, setPlaceholderValue] = useState<string>("");
  const [inputActive, setInputActive] = useState<boolean>(false);

  const onFocus = () => setInputActive(true);
  const onBlur = () => {
    setInputActive(false);
  };

  const updateAddedState = useCallback(() => {
    console.log("running");
    
    updateState(addedItems);
  }, [updateState, addedItems]);

  const handleFilter = (e: React.ChangeEvent<HTMLInputElement>) => {
    setSearchTerm(e.target.value);
  };

  const handleFilterData = useCallback(
    (searchTerm: string) => {
      let newFilter = data.filter((value) => {
        return value.name.toLowerCase().includes(searchTerm.toLowerCase());
      });

      for (let i = 0; i < addedItems.length; i++) {
        for (let j = 0; j < newFilter.length; j++) {
          if (addedItems[i].id === newFilter[j].id) {
            newFilter.splice(j, 1);
          }
        }
      }

      setFilteredData(newFilter);
    },
    [addedItems, data]
  );

  const addItem = (value: IData) => {
    setAddedItems([...addedItems, value]);
    setSearchTerm("");
    handleFilterData("");
    setInputActive(false);
  };

  const removeItem = (value: IData, e: React.MouseEvent) => {
    e.preventDefault();
    let newArray: IData[] = [];

    for (let i = 0; i < addedItems.length; i++) {
      newArray.push(addedItems[i]);
    }

    for (let i = 0; i < newArray.length; i++) {
      if (value.id === newArray[i].id) {
        newArray.splice(i, 1);
      }
    }
    setAddedItems(newArray);
    setInputActive(true);
  };

  useEffect(() => {
    if (addedItems.length === 1) {
      setPlaceholderValue(`${addedItems.length} vald`);
    } else if (addedItems.length > 1) {
      setPlaceholderValue(`${addedItems.length} valda`);
    } else {
      setPlaceholderValue(placeholder);
    }
  }, [addedItems, placeholderValue, placeholder]);

  useEffect(() => {
    handleFilterData(searchTerm);
  }, [searchTerm, addedItems, handleFilterData]);

  useEffect(() => {
    let isMounted = true;
    if (isMounted) {
      if (addedItems) {
        updateAddedState();
      }
    }

    return () => {
      isMounted = false;
    };
  }, [updateAddedState, addedItems]);

  return (
    <div id="dropdownMulti">
      <section className="inputSection">
        <input
          type="text"
          placeholder={placeholderValue}
          className="inputSection__input"
          onChange={handleFilter}
          value={searchTerm}
          onFocus={onFocus}
          onBlur={onBlur}
        />
        <div className="inputSection__icon-container">
          {inputActive ? (
            <AiOutlineUpCircle
              onClick={() => setInputActive(false)}
              className="inputSection__icon-container--up"
            />
          ) : (
            <AiOutlineDownCircle className="inputSection__icon-container--down" />
          )}
        </div>
      </section>
      <section className="addedItems-section">
        {inputActive &&
          addedItems.map((addedItem) => {
            return (
              <div className="addedItem" key={addedItem.id}>
                <p className="addedItem__item">{addedItem?.name}</p>
                <button
                  data-testid="remove-btn"
                  className="addedItem__button"
                  onMouseDown={(e: React.MouseEvent) =>
                    removeItem(addedItem, e)
                  }
                >
                  <AiOutlineCloseCircle />
                </button>
              </div>
            );
          })}
      </section>
      {inputActive && (
        <ul className="dataResult">
          {filteredData.slice(0, 10).map((value) => {
            return (
              <li
                className="dataResult__item"
                key={value.id}
                tabIndex={0}
                onMouseDown={() => addItem(value)}
              >
                {value.name}
              </li>
            );
          })}
        </ul>
      )}
    </div>
  );
};


关于如何减少运行次数的任何提示?

尝试删除 React Strict Mode,它使组件仅在开发中渲染两次,而不是在生产中。 如果是这种情况,请重新安装。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM