可参考文章:https://mp.weixin.qq.com/s/2ayQpXkGjsvUnBm7KPIYMg
1,封装 invariant函数来避免 | undefined 和 | null报错 (类型守卫)
ts
function invariant(condition:any,message?:string | (()=>string)):asserts condition{
if(!condition){
const errorMessage = typeof message === 'function' ? message() : message || 'Invariant violation';
console.error("errorMessage",errorMessage)
}
}
2, 封装HOC高阶组件转发Ref
ts
function WithForwardedRef<T,P={}>(Component: React.ComponentType<T>){
return forwardRef<T,P>((props,ref)=>{
return <Component props={...props} ref={ref}/>
})
}
3,twcss样式类名小寄巧
ts
import type { ClassValue } from "clsx";
import { clsx } from "clsx";
import { twMerge } from "tailwind-merge";
const cn = (...inputs: ClassValue[]) => {
return twMerge(clsx(inputs));
};
export default cn;
4,
ts
type User = {
id: number;
name: string;
};
type UserRecord = Record<string, User>;
const users: UserRecord = {
user1: { id: 1, name: 'Alice' },
user2: { id: 2, name: 'Bob' },
};
5, 避免ref相关的问题
ts
// ❌ 错误示例:使用 ComponentProps
interface BadProps extends React.ComponentProps<"div"> {
customProp: string;
}
// 这会导致类型错误,因为组件没有正确处理 ref
const BadComponent = (props: BadProps) => {
return <div {...props} />;
};
// ✅ 正确示例:使用 ComponentPropsWithoutRef
interface GoodProps extends React.ComponentPropsWithoutRef<"div"> {
customProp: string;
}
const GoodComponent = (props: GoodProps) => {
return <div {...props} />;
};
6, forwardRef的正确使用
tsx
// 如果需要处理 ref,应该明确使用 forwardRef
interface ButtonProps extends React.ComponentPropsWithoutRef<"button"> {
variant?: 'primary' | 'secondary';
}
// 正确处理 ref
const Button = React.forwardRef<HTMLButtonElement, ButtonProps>(
(props, ref) => {
const { variant, ...rest } = props;
return (
<button
ref={ref}
className={variant}
{...rest}
/>
);
}
);
tsx
// ✅ 正确示例:使用 forwardRef
interface ButtonProps extends React.ComponentPropsWithoutRef<"button"> {
label: string;
}
const Button = forwardRef<HTMLButtonElement, ButtonProps>((props, ref) => {
const { label, ...rest } = props;
return <button ref={ref} {...rest}>{label}</button>;
});
// 使用时 ref 可以正确工作
const App = () => {
const buttonRef = useRef<HTMLButtonElement>(null);
return <Button ref={buttonRef} label="Click me" />; // ref 正常工作
}
在React19中,有新写法: props直接合入ref当中
tsx
// React 19 的新写法
interface ButtonProps {
label: string;
ref?: React.Ref<HTMLButtonElement>; // ref 直接作为 props
}
const Button = (props: ButtonProps) => {
const { label, ref, ...rest } = props;
return <button ref={ref} {...rest}>{label}</button>;
};
// 使用方式
const App = () => {
const buttonRef = useRef<HTMLButtonElement>(null);
return <Button ref={buttonRef} label="Click me" />;
}
7,
ts
// ❌ 可能的问题:ref 类型不匹配
interface ProblematicProps extends React.ComponentProps<"div"> {
innerRef?: React.RefObject<HTMLDivElement>; // 与原生 ref 冲突
}
// ✅ 正确方式:
interface SafeProps extends React.ComponentPropsWithoutRef<"div"> {
innerRef?: React.RefObject<HTMLDivElement>; // 不会与原生 ref 冲突
}