如果我添加 PropTypes,我需要检查 typeof 吗?

If I add PropTypes, do I need to check typeof?

我有一个道具 onNotifyChange,它是一个函数,我在输入的 onChange 中调用它。

它有一个 func 的 PropType。

MyComponent.propTypes = {
    onNotifyChange: PropTypes.func,
}

调用onNotifyChange时,是否需要检查typeof

const onChange = e => {
    // do some stuff
    if(onNotifyChange && typeof onNotifyChange === 'function'){
        onNotifyChange()
    }
}

或者只是检查它是否是假的?

const onChange = e => {
    // do some stuff
    if(onNotifyChange){
        onNotifyChange()
    }
}

PropTypes.bar 是否不需要检查 typeof foo === 'bar'

取决于:一般情况下,没有;在实践中...也许。

类型检查不会(通常)发生在生产构建中。如果您有类型可能无效的动态构造属性,那么您仍然需要某种形式的错误处理。

来自prop-types package

and warn in development if they don’t match

所以 prop-types 只有 "protect" 你在开发 时不会犯错误 。当你的代码是 运行 时它什么都不做(除了在控制台上抛出错误)。

如果您需要硬类型检查,请使用typescript...虽然即使那些只是在开发+构建期间,所以...JS 中没有任何东西可以保护您在运行时免受错误类型的影响(除了编写时显式检查),因为它毕竟是一种弱类型语言。

最好定义 defaultProps。

MyComponent.defaultProps = {
    onNotifyChange: () => false
}

这将解决您 "forget" 传递 onNotifyChange 的情况。

如果不定义 defaultProps,你会 运行 进入,

Uncaught TypeError: _this10.props.onNotifyChange is not a function

是的,即使使用 prop-types,您也需要检查道具的类型。 prop-types 库在 React 开发模式下给你运行时警告。

在下面的示例中,我们使用的是 React 的开发版本。我们有一个组件 H1 具有必需的函数 prop。请注意,在 App 中使用 H1 组件时,如果没有为 className 属性传递值,则会引发错误, prop-types 已记录警告。

因此,您不能依靠 prop-types 来防止不良道具被传递给 children。

function H1({ className, children }) {
  // this will throw if className is not a function
  return <h1 className={className()}>{children}</h1>
}

H1.propTypes = {
  className: PropTypes.func.required
} 

function App() {
  return <H1>Test</H1>
}

ReactDOM.render(<App />, document.querySelector("#root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.7.2/prop-types.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.development.js"></script>
<div id=root></div>

要防止这种事情在运行时发生,您可以:

  • 声明道具的默认值
  • 对组件内 prop 的值进行验证

更好的是,您可以同时执行这两项操作,如下例所示:

function H1({ className, children }) {
  /* do some validation of your props 
     (throwing here to demonstrate that the default prop set below 
     works - I do not recommend throwing errors within components
     like this unless you know what you're doing, e.g. have an error
     boundary to catch behaviour like this) */
  if (typeof className !== "function") {
    throw new Error("expecting className prop to be function")
  }
  return <h1 className={className()}>{children}</h1>
}

H1.propTypes = {
  className: PropTypes.func.required
} 

H1.defaultProps = {
  className: () => ""
}

function App() {
  return <H1>Test</H1>
}

ReactDOM.render(<App />, document.querySelector("#root"))
<script src="https://cdnjs.cloudflare.com/ajax/libs/prop-types/15.7.2/prop-types.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.12.0/umd/react.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.11.0/umd/react-dom.development.js"></script>
<div id=root></div>

这样你的应用程序就不会因为错误的属性值而崩溃,并且在开发模式下你会看到 prop-types.

记录的警告