reactjs - 将 React 子组件实现为只有特定组件时如何解决类型问题?
问题描述
我正在尝试实现一种 React 子组件验证以仅具有特定组件但面临类型问题。
请在下面查看我的代码:
// a component needs the validation
import { Children, FunctionComponent, isValidElement } from 'react';
import { AccordionProps } from '@components/old/signup/organisms/accordion/interfaces';
import CheckFormField from '@components/old/signup/organisms/checkFormField';
import AccordionHeader from '@components/old/signup/organisms/accordionHeader';
const Accordion: FunctionComponent<AccordionProps> = ({ children }) => {
const allowedComponents = [CheckFormField, AccordionHeader]; // these can only be children
Children.map(children, (child) => {
const childType = isValidElement(child) && child.type;
if (!allowedComponents.includes(childType)) { // here comes type error to use includes method
throw new Error('Error message..');
}
});
:
:
return (
<div>{children}</div>
);
上面代码的类型错误:
TS2345: Argument of type 'string | false | JSXElementConstructor<any>' is not assignable to parameter of type 'FunctionComponent<CheckFormFiledProps> | FunctionComponent<AccordionHeaderProps>'. Type 'string' is not assignable to type 'FunctionComponent<CheckFormFiledProps> | FunctionComponent<AccordionHeaderProps>'.
以及我在下面定义的道具:
// interfaces.ts
export interface AccordionProps {
children: ReactElement<any> | ReactElement[];
}
我怀疑上面的儿童道具可能不是合适的类型,但到目前为止没有运气搜索它。
参考:
在 React 和 Typescript 中只允许特定组件作为子组件
提前致谢。
解决方案
对此的一种可能解决方案是通过组件属性而不是 classicchildren
将目标子组件传递给父组件。让我们调用子组件属性Components
,以区别于标准children
。
下面是子组件数组是如何验证(由 TypeScript 本身)并通过Main
组件呈现的:
// Main.tsx
import ValidChildOne from './ValidChildOne';
import ValidChildTwo from './ValidChildTwo';
// declaring what is allowed as children
type AllowedChild = typeof ValidChildOne | typeof ValidChildTwo;
interface MainProps {
Components: AllowedChild[]; // array
}
export default function Main({ Components }: MainProps) {
return (
<>
<h1>Main</h1>
{
Components.map((Child, index) => <Child key={index} />)
}
</>
);
}
以下是Main
组件(及其道具)的应用方式:
// App.tsx
import Main from './Main';
import ValidChildOne from './ValidChildOne';
import ValidChildTwo from './ValidChildTwo';
export default function App() {
return (
<Main Components={[ValidChildOne, ValidChildTwo]} />
);
}
最后,子组件的代码供参考:
// ValidChildOne.tsx
export default function ValidChildOne() {
return <h2>ValidChildOne</h2>;
}
// ValidChildTwo.tsx
export default function ValidChildTwo() {
return <h2>ValidChildTwo</h2>;
}
推荐阅读
- jackson - Apache Camel 3.4 - 使用 Jackson 的各种解组错误
- json - 如何停止 Powershell 7 ConvertFrom-Json 重新格式化时间戳?
- javascript - 将 WebStorage (JS/JQuery) 内容转换为 Blade-ready 变量
- php - How to connect wss via ReactPHP components
- angular - angular reactive form can't remove null item
- apache-kafka - How do I define the type of a field starting with a @?
- r - R: Replace multiple strings with a single string in R
- cobol - COBOL: What is the benefit of using paragraphs and sections instead of subprograms?
- objective-c - 我该如何处理这种欧式时间戳?
- java - What should be the name of the prev_node argument passed into the method given below?