React+TypeScript中向作为参数传入的函数组件传递props的方法
现有实现存在的问题
- 组件调用方式不符合React规范:直接调用函数组件
props.functionalComp(...item)而不是使用JSX语法渲染,无法触发React的组件生命周期、hooks等逻辑,运行会出现异常 - React函数组件参数定义错误:标准React函数组件仅接收单个props对象作为参数,你定义的
Task、Project组件直接拆分了name/content等多个参数,不符合组件规范 - 属性名不匹配:容器组件
DisplayFCs定义接收的props数组字段是itemArray,但调用时传的是propsArray,运行时会找不到数组直接报错 - 缺少map渲染的key属性:列表渲染没有给每个子项加唯一key,会触发React的key警告,影响Diff性能
- TypeScript类型无约束:当前用
any定义props,没有关联组件和对应props的类型,无法享受TS的类型校验能力,传错属性也不会提示
调整方案
1. 改造泛型容器组件DisplayFCs
用TS泛型绑定组件和对应props的类型,修正组件渲染方式,补充key属性:
import React from 'react'; // 泛型T代表传入组件的props类型 interface DisplayFCsProps<T extends object> { propsArray: T[], functionalComp: React.FC<T> } export default function DisplayFCs<T extends object>(props: DisplayFCsProps<T>) { return ( <div> {props.propsArray.map((item, index) => { // 实际业务建议用item里的唯一字段比如id作为key,这里用index做演示 const Comp = props.functionalComp return <Comp key={index} {...item} /> })} </div> ) }
2. 修正子组件定义,符合React函数组件规范
每个组件仅接收单个props对象,同时定义明确的props类型:
// Task组件props定义 interface TaskProps { name: string; content: string; } const Task: React.FC<TaskProps> = (props) => { return( <div> <p>{props.name}</p> <p>{props.content}</p> </div> ) }; // Project组件props定义 interface ProjectProps { name: string; status: string; } const Project: React.FC<ProjectProps> = (props) => { return ( <div> <p>{props.name}</p><p>{props.status}</p> </div> ) }
如果你不习惯用React.FC定义组件,也可以直接写成普通函数,只要保证参数是单个props对象即可:
function Task(props: TaskProps) { return( <div> <p>{props.name}</p> <p>{props.content}</p> </div> ) }
3. 调用逻辑保持属性名匹配即可
import React from 'react'; import DisplayFCs from './DisplayFCs'; const taskPropsArray: TaskProps[] = [ {name: "jog", content: "Run in park"}, {name: "walk dog", content: "Give Treat when done"}, ] const projectPropsArray: ProjectProps[] = [ {name: 'Program', status: "active" }, {name: "Pilot", status:"inactive"}, ] export default function DemoProblem(){ return( <> <DisplayFCs functionalComp={Task} propsArray={taskPropsArray} /> <DisplayFCs functionalComp={Project} propsArray={projectPropsArray} /> </> ) }
内容的提问来源于stack exchange,提问作者lslak
相关产品推荐
相关产品推荐

