如何为Button
组件(如下)添加打字稿类型,以便打字稿知道increment
HOC已注入Counter
函数?
我知道了渲染道具图案和挂钩。我正在专门寻找一种类型的子组件,该子组件可以通过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'));
答案 0 :(得分:0)
不幸的是,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
,从而在渲染最终的foo
时必须提供Counter
。
如果在渲染foo="bar"
时删除Counter
,您会发现我们遇到类型错误。