React组件调度通用有效载荷



我试图创建一个可重用的<Column />组件,该组件显示一个项目列表,每个项目在单击时都会分派调用方指定的通用负载。

我的专栏采用了一个onItemClick道具,它是一个调度有效负载的函数(在我的实际代码中是一个Redux操作(。我希望我的函数能够接受和调度通用<PayloadType>:

type ColumnProps<PayloadType> = {
menuItems: { name: string; id: number }[];
onItemClick: (payload: PayloadType) => void;
};
const Column = <PayloadType extends {}>(
props: React.PropsWithChildren<ColumnProps<PayloadType>>
) => {
const { menuItems, onItemClick } = props;
const handleButtonClick = (menuItem: MenuItem) => {
onItemClick({ info: menuItem.name });
/* 
Argument of type '{ info: string; }' is not assignable to parameter of type 
'PayloadType'.
'{ info: string; }' is assignable to the constraint of type 'PayloadType', but 
'PayloadType' could be instantiated with a different subtype of constraint '{}'
*/
};
return (
<>
{menuItems.map((menuItem, index) => (
<button key={index} onClick={(event) => handleButtonClick(menuItem)}>
{menuItem.name}
</button>
))}
</>
);
};

使用组件:

type MenuItem = {
name: string;
id: number;
};
const testMenuItems: MenuItem[] = [
{ name: "Vanilla", id: 0 },
{ name: "Strawberry", id: 1 },
{ name: "Chocolate", id: 2 },
{ name: "Cookies & Cream", id: 3 }
];
type ColumnPayload = {
info: string;
};
export default function App() {
const columnClickHandler = (payload: ColumnPayload) => {
console.log(`clicked: ${payload.info}`);
};
return (
<div className="App">
<Column<ColumnPayload>
menuItems={testMenuItems}
onItemClick={columnClickHandler}
/>
</div>
);
}

如上所述,我收到错误:

Argument of type '{ info: string; }' is not assignable to parameter of type 'PayloadType'.
'{ info: string; }' is assignable to the constraint of type 'PayloadType', but 'PayloadType' could be instantiated with a different subtype of constraint '{}'.

如何从我的组件接受和调度通用有效负载?我是TypeScript的新手,所以我不确定我是遗漏了什么,还是只是完全错误地处理了问题。

沙盒:https://codesandbox.io/s/sweet-kalam-tt5u5?file=/src/App.tsx

这里的问题是Column在没有帮助的情况下无法创建特定类型,它只能知道存在一些未知类型。

类型交叉点

也就是说,实现通用回调的一种方法就是简单地将有效负载类型与菜单项联合起来。

type MenuItemWithPayload<TPayload> = MenuItem & Payload

然后用整个菜单项调度回调。我提供了一些示例代码,注意到ColumnMenuItem是如何既是有效负载又是菜单项类型的?如果在使用列组件时不再需要定义有效负载类型,则可以进行类型推断。

https://codesandbox.io/s/eager-framework-pu4qe?file=/src/App.tsx.

通用有效载荷字段

更干净的替代方案可能是允许菜单项包含有效载荷字段。它类似于并集类型,但使用了组合。

type MenuItem<TPayload = unknown> = { name: string; id: number; payload: TPayload }

https://codesandbox.io/s/friendly-currying-g1ynk?file=/src/App.tsx

转发菜单项

最后,您可以简单地转发回调中的菜单项,并让父组件生成所需的负载。

https://codesandbox.io/s/hardcore-surf-ihz96?file=/src/App.tsx

相关内容

最新更新