繁体   English   中英

打字稿抱怨反应组件可选道具可能未定义

[英]Typescript complains that react component optional prop could possibly be undefined

我有一个像这样的简单 React 组件:

interface ComponentProps {
    onClick?: () => void;
}

const Component = (props: ComponentProps) => {
    if (!props.onClick) {
        return <></>;
    }

    return (
        // Typescript complains: Cannot invoke an object which is possibly 'undefined'.ts(2722)
        <button onClick={() => props.onClick()}>  
            test
        </button>
    );
};

Typescript 抱怨 props.onClick 可能未定义,即使在检查之后也是如此。

谁能帮我理解为什么 props.onClick仍然可能是未定义的?

这是因为您使用的是可选的属性运算符? 进入ComponentProps接口定义。

我看到有两种方法可以解决这个问题:

第一个是将可选属性定义更改为强制删除? 可选的属性运算符,因此您无需验证onClick函数是否传递给组件。

interface ComponentProps {
   onClick: () => void;
}
const Component = ({onClick}) => (
   <button onClick={onClick}>
       test
   </button> 
)

l 第二个是创建一个处理函数来验证可选的onClick函数。

inteface ComponentProps {
    onClick?: () => void;
}
const Component = ({onClick}: ComponentProps) => (
   <button onClick={() => {
       if(onClick) onClick();
   }}>  
       test
   </button>
)

奖金。 您可以同时使用扩展语法和三元运算符来验证传递给 React 组件的可选属性。

interface ComponentProps {
   onClick?: () => void;
}
const Component = ({onClick}: ComponentProps) => (
   <button {...(onClick ? {onClick} : {})}>test</button>
)

问题是你的props对象是可变的,TypeScript 假设它可以在你的!props.onClick检查和回调执行之间修改。

要解决您的问题,您可以解构props对象并将onClick属性用作范围变量:

const Component = ({onClick}: ComponentProps) => {
    if (!onClick) {
        return <></>;
    }

    return (
        <button onClick={() => onClick()}>  
            test
        </button>
    );
};

你为什么不试试

interface ComponentProps {
    onClick?: () => void;
}

const Component = ({ onClick = () => {}}: ComponentProps) => {


    return (
      
        <button onClick={() => props.onClick()}>  
            test
        </button>
    );
};

使用props.onClick?.()而不是props.onClick()

这告诉打字稿只有在定义时才调用 onClick() 。

在此处了解有关可选链接的更多信息

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM