在JSX中调用时,由自定义钩子返回的组件会触发ts错误

时间:2020-08-28 13:37:15

标签: reactjs typescript react-hooks

我创建了该自定义钩子

// 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忽略就无法编译。

感谢您的帮助

1 个答案:

答案 0 :(得分:0)

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

无论何时我们在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>;
}