gpt4 book ai didi

reactjs - 如何在保持类型非可选的同时抽象传递重复的子属性?

转载 作者:搜寻专家 更新时间:2023-10-30 20:43:15 27 4
gpt4 key购买 nike

我有一个连续多次使用的组件,它具有一些相同的属性和一些独特的属性:

interface InsideComponentProps {
repeatedThing: string;
uniqueThing: string;
}

const InsideComponent: React.SFC<InsideComponentProps> = ({ repeatedThing, uniqueThing }) => (
<div>{repeatedThing} - {uniqueThing}</div>
);

const Example = () => (
<div>
<InsideComponent repeatedThing="foo" uniqueThing="1" />
<InsideComponent repeatedThing="foo" uniqueThing="2" />
<InsideComponent repeatedThing="foo" uniqueThing="3" />
</div>
);

重复的 repeatedThing 属性困扰着我,所以我正在寻找一种方法来消除这种冗余。我在非 TypeScript 应用程序中做过的一件事是引入一个包装器组件来克隆所有子项,并在此过程中添加重复的属性:

interface OutsideComponentProps {
repeatedThing: string;
}

const OutsideComponent: React.SFC<OutsideComponentProps> = ({ repeatedThing, children }) => (
<div>
{React.Children.map(children, (c: React.ReactElement<any>) => (
React.cloneElement(c, { repeatedThing })
))}
</div>
);

const Example = () => (
<OutsideComponent repeatedThing="foo">
<InsideComponent uniqueThing="1" />
<InsideComponent uniqueThing="2" />
<InsideComponent uniqueThing="3" />
</OutsideComponent>
);

生成的 JavaScript 代码具有我想要的行为,但 TypeScript 编译器有错误,因为我在实例化 InsideComponent 时没有传递所有必需的属性:

ERROR in [at-loader] ./src/index.tsx:27:26
TS2322: Type '{ uniqueThing: "1"; }' is not assignable to type 'IntrinsicAttributes & InsideComponentProps & { children?: ReactNode; }'.
Type '{ uniqueThing: "1"; }' is not assignable to type 'InsideComponentProps'.
Property 'repeatedThing' is missing in type '{ uniqueThing: "1"; }'.

我想到的唯一解决方案是将 InsideComponentrepeatedThing 属性标记为可选,但这并不理想,因为值需要。

我如何保持严格性以确保 InsideComponent 确实接收到所有 props,同时减少调用站点属性的重复?

我正在使用 React 16.2.0 和 TypeScript 2.6.2。

最佳答案

TypeScript 检查以确保您将所有必需的属性分配给 React 元素。由于您在 OutsideComponent 中分配了额外的属性编译器无法真正检查。

一个选项是将子项指定为一个函数,该函数将额外的属性作为参数并将它们传播到 InsideComponent .语法有点复杂,但类型更安全:

interface OutsideComponentProps {
repeatedThing: string;
children: (outerProps: OutsideComponentProps) => React.ReactElement<any>;
}

const OutsideComponent: React.SFC<OutsideComponentProps> = (o) => o.children(o);

const Example = () => (
<OutsideComponent repeatedThing="foo">{(o) =>
<div>
<InsideComponent uniqueThing="1" {...o} />
<InsideComponent uniqueThing="2" {...o} />
<InsideComponent uniqueThing="3" {...o} />
</div>
}</OutsideComponent>
);

It seems that OutsideComponent is very abstract and thus reusable; is there any way to convert it into a very generic component that takes all of its props and provides them as the argument, without having to define an OutsideComponentProps for each case?

虽然您可以将泛型函数用作组件,但您不能显式指定类型参数,它们只能被推断。这是一个缺点,但最终可以解决。

function GenericOutsideComponent<T>(props: { children: (o: T) => React.ReactElement<any> } & Partial<T>, context?: any): React.ReactElement<any> {
return props.children(props as any);
}

const Example = () => (
<GenericOutsideComponent repeatedThing="foo">{(o: InsideComponentProps) =>
<div>
<InsideComponent uniqueThing="1" {...o} />
<InsideComponent uniqueThing="2" {...o} />
<InsideComponent uniqueThing="3" {...o} />
</div>
}</GenericOutsideComponent>
);

与您的原始 JavaScript 解决方案类似,存在 InsideComponent 的某些必需属性存在风险未指定为 GenericOutsideComponent 的属性是 Partial<T> (只允许指定 repeatedThing)和 oT因为否则编译器会考虑 repeatedThing未指定,将在 InsideComponent 上需要它.如果在 InsideComponent 上设置虚拟值没问题,只需更改children的签名即可至 (o: Partial<T>) => React.ReactElement<any>但这不太理想。

另一种选择是明确哪些属性在 GenericOutsideComponent 上使用 Pick :

function GenericOutsideComponent<T>(props: { children: (o: T) => React.ReactElement<any> } & T, context?: any): React.ReactElement<any> {
return props.children(props);
}

const Example = () => (
<GenericOutsideComponent repeatedThing="foo">{(o: Pick<InsideComponentProps, "repeatedThing">) =>
<div>
<InsideComponent uniqueThing="1" {...o} />
<InsideComponent uniqueThing="2" {...o} />
<InsideComponent uniqueThing="3" {...o} />
</div>
}</GenericOutsideComponent>
);

关于reactjs - 如何在保持类型非可选的同时抽象传递重复的子属性?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/48435346/

27 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com