【问题标题】:Typescript type for child component of a higher order component that adds a prop添加道具的高阶组件的子组件的打字稿类型
【发布时间】:2019-07-20 12:38:30
【问题描述】:

如何为Button 组件(如下)添加打字稿类型,以便打字稿知道increment 函数已被Counter HOC 注入?

我知道渲染道具模式和钩子。我正在寻找一种方法来键入子组件,这些子组件通过cloneElement 接收父组件的道具。

我感觉它与条件类型有关,但不知道如何应用它。这甚至可能吗?

import React from 'react';

const Button = ({ increment }) => (
  <button onClick={increment}>
    increment
  </button>
);

const Counter = ({ children }) => {
  const [count, setCount] = React.useState(0);
  const increment = () => setCount(count + 1)

  return (

  <div>
    count: {count}
    {React.cloneElement(children, { increment })}
  </div>
  );
}

const App = () => (
  <Counter>
    <Button>
      increment
    </Button>
  </Counter>
);

ReactDOM.render(<App />, document.getElementById('root'));

【问题讨论】:

  • 尝试:{增量}:任何{孩子}:任何

标签: reactjs typescript


【解决方案1】:

不幸的是,TypeScript 为 JSX 子代处理类型的方式不是很好,cloneElement 也是如此。在您的情况下,Button 必须有一个可选的 increment 属性,这意味着您稍后必须检查它是否存在。

我会推荐以下模式:

import React, { ComponentType } from 'react';
import ReactDOM from 'react-dom';

interface InjectedCounterProps {
  increment: () => void;
}

interface ButtonOwnProps {
  foo: string;
}

type ButtonProps = ButtonOwnProps & InjectedCounterProps;

const Button = ({ increment }: ButtonProps) => (
  <button onClick={increment}>increment</button>
);

const createCounter = <P extends {}>(
  Component: ComponentType<P & InjectedCounterProps>
) => (props: P) => {
  const [count, setCount] = React.useState(0);
  const increment = () => setCount(count + 1);

  return (
    <div>
      count: {count}
      <Component {...props} increment={increment} />
    </div>
  );
};

const Counter = createCounter<ButtonOwnProps>(Button);

const App = () => <Counter foo="bar" />;

ReactDOM.render(<App />, document.getElementById('root'));

这里我们使用 HOC 从提供的 Button 组件构造我们的组件,并且我们能够将此按钮的类型限制为由 HOC 注入的类型。

这也允许应用到返回组件的 props 由我们提供的组件定义。这是通过通用的P 类型参数完成的,并允许我们传递ButtonOwnProps,强制在渲染我们的最终Counter 时必须提供foo

如果您在渲染 Counter 时删除 foo="bar",您会注意到我们会收到类型错误。

【讨论】:

    猜你喜欢
    • 2019-06-21
    • 2019-06-26
    • 2021-11-10
    • 2020-11-09
    • 2021-04-14
    • 2019-05-30
    • 2021-11-23
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多