首页 > 解决方案 > 自定义钩子返回的组件在 JSX 中调用时触发 ts 错误

问题描述

我创建了那个自定义钩子

// useDropdown.ts
function useDropdown(defaultState: number, options: number[]) {
  const [state, setState] = useState(defaultState);
  function Dropdown({ name }: { name: string }) {
    return (
      <>
        <select
          name={name}
          value={state}
          onChange={(e) => setState(Number(e.target.value))}
          onBlur={(e) => setState(Number(e.target.value))}
          disabled={options.length === 0}
        >
          {options.map((item) => (
            <option key={item} value={item}>
              {item}h
            </option>
          ))}
        </select>
      </>
    );
  }

  return [state, Dropdown, setState];
}

export default useDropdown;
// HourPicker.ts
const HourPicker = ({ day, label }: HourPickerProps) => {
  const [checked, changeChecked] = useState(
    day.startHour && day.endHour ? true : false
  );

  const [startHour, StartHourDropdown] = useDropdown(day.startHour || 9, hours);
  const [endHour, EndHourDropdown] = useDropdown(day.endHour || 18, hours);

  function useChecked() {
    changeChecked(!checked);
  }

  return (
    <HourPickerContainer checked={checked}>
          <p>
            De <StartHourDropdown name={`${label}-start`} /> à{" "}
            <EndHourDropdown name={`${label}-end`} />
          </p>
    </HourPickerContainer>
  );
};

当我使用钩子返回的组件Dropdown时,我收到此错误:

JSX element type 'StartHourDropdown' does not have any construct or call signatures.

这个组件运行良好,但每次调用我的组件时,如果不编写 ts 忽略,我就无法编译。

谢谢你的帮助

标签: reactjstypescriptreact-hooks

解决方案


这里的问题是构造函数和实例之间的混淆。

每当我们在 React 中编写组件时:

class Greeter extends React.Component<any, any> {
    render() {
        return <div>Hello, {this.props.hello}</div>;
    }
}

你这样使用它:

return <Greeter hello='world' />;

而不是这样:

let Greet = new Greeter();
return <Greet whoToGreet='world' />;

在第一个示例中,我们传递了 Greeter,这是我们组件的构造函数。那是准确的用法。在第二个例子中,我们传递了一个 Greeter 的实例。这是不正确的,并且会在运行时产生错误,例如“对象不是函数”。

这段代码的问题

function renderGreeting(Elem: React.Component<any, any>) {
    return <span>Hello, <Elem />!</span>;
}

是它期待一个 React.Component 的实例。我们想要的是一个带有 React.Component 构造函数的函数:

function renderGreeting(Elem: new() => React.Component<any, any>) {
    return <span>Hello, <Elem />!</span>;
}

或类似地:

function renderGreeting(Elem: typeof React.Component) {
    return <span>Hello, <Elem />!</span>;
}

推荐阅读