React 在自定义钩子中返回一个函数,其内部钩子返回一个对象

时间:2021-02-10 17:11:16

标签: reactjs react-hooks

我最近升级了我的 use-debounce 反应包。突破性的变化是钩子返回了一个对象而不是一个数组。我无法更新钩子以使其适用于新更改。 I have created a codesandbox to demonstrate the issue,设置状态失败,因为从钩子返回的设置器没有正确配置。出于沙箱的目的,我将钩子组件放入主组件中,以便所有信息都集中在一个位置。

错误是setState is not a function

如果您不想看,这里是沙箱中的代码

const Input = () => {
  // hook that would normally be in a seperate component
  const useDebouncedState = (
    initialState,
    durationInMs = 200,
    options = {}
  ) => {
    const [internalState, setInternalState] = useState(initialState);
    const debouncedSetter = useDebouncedCallback(
      () => debouncedSetter.callback(setInternalState),
      durationInMs,
      options
    );
    return [internalState, debouncedSetter];
  };

  // this would be set in the main components
  const [searchText, setSearchText] = useDebouncedState("", 200, {
    maxWait: 1000
  });

  // this is where i set
  return (
    <>
      <input type="text" onChange={(e) => setSearchText(e.target.value)} />
      <h1>{searchText}</h1>
    </>
  );
};

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

2 个答案:

答案 0 :(得分:2)

问题出在这段代码上:

const debouncedSetter = useDebouncedCallback(
  // debouncedSetter in this scope is undefined, but linter doesn't catch it
  () => debouncedSetter(setInternalState),
  durationInMs,
  options
);

debouncedSetterundefined,因为您从未声明过它,因此由于闭包,它会在 callback() 上调用 undefined,这会导致运行时错误。

如果您将代码更改为下一个代码段,您会注意到 linting 警告:

const useDebouncedState = (initialState, durationInMs = 200, options = {}) => {
  const [internalState, setInternalState] = useState(initialState);
  const callback = useDebouncedCallback(
    // 'debouncedSetter' is not defined
    () => debouncedSetter(setInternalState),
    durationInMs,
    options
  );
  return [internalState, callback];
};

答案 1 :(得分:1)

感谢所有发帖的人,这让我找到了答案。工作代码是

import React, { useState } from "react";
import ReactDOM from "react-dom";
import useDebouncedCallback from "use-debounce/lib/useDebouncedCallback";

const Input = () => {
  // hook that would normally be in a seperate component
  const useDebouncedState = (
    initialState,
    durationInMs = 200,
    options = {}
  ) => {
    const [internalState, setInternalState] = useState(initialState);
    const debouncedSetter = useDebouncedCallback(
      setInternalState,
      durationInMs,
      options
    );
    return [internalState, debouncedSetter];
  };

  // this would be set in the main components
  const [searchText, setSearchText] = useDebouncedState("", 800, {
    maxWait: 1000
  });

  // this is where i set
  return (
    <>
      <input
        type="text"
        onChange={(e) => setSearchText.callback(e.target.value)}
      />
      <h1>{searchText}</h1>
    </>
  );
};

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