React: 警告:PropTypes.object.isRequired 当 prop 为 `null`

创建于 2015-02-16  ·  37评论  ·  资料来源: facebook/react

由于PropTypes是关于 prop 的“类型”,因此null是一个空对象,但实际上仍然是一种对象。

但它仍然警告:

 Warning: Required prop `profile` was not specified in `Element`. Check the render method of `OtherElement`.

我认为这不应该发生。

它不再是null后停止警告。 我很确定它应该只在undefined时发出警告?

最有用的评论

我看到的一个常见用例是 React 在对数据的 API 调用完成之前渲染组件。 例如,第一个渲染将渲染一个项目列表 ( items: null )。 然后 API 调用完成,现在items填充了一个数组。

所有37条评论

null相当于没有值并且不是对象(空或其他)。 如果您不希望它为null发出警告,则不要让它成为必需,它具有相同的效果。 我不建议测试密钥的存在。

我同意。 我想不出很多用例,您希望强制用户指定一个值,但又愿意接受 null 作为有效值。 出于实际目的,空值的 isRequired 警告是明智的和预期的行为。

相关: https :
(此问题仍然在搜索结果中突出显示)

我看到的一个常见用例是 React 在对数据的 API 调用完成之前渲染组件。 例如,第一个渲染将渲染一个项目列表 ( items: null )。 然后 API 调用完成,现在items填充了一个数组。

我正在尝试执行PropTypes.oneOfType([null, PropTypes.object]).isRequired ,所以无论是 null 还是一个对象,这现在不可能吗?

根据CHANGELOG ,因为15.4.0它被认为是可能的

实际上,在 15.4.0 中正好相反: Required PropTypes now fail with specific messages for null and undefined.

我也面临这个问题。
@Noitidart的解决方法对我不起作用。 它抛出一个错误说:
Failed prop type: The propis marked as required in选择, but its value is null .

我发现要求一个属性但也允许空值真的很有用。

+1 以某种方式允许null

我们有一个用例,我们的配置通过 JSON 加载,并且有几个标签配置选项指定应该显示的字符串,如下所示:

{
  "title": "my title"
}

所以当不应该显示标题时,我们使用null来表示这种情况:

{
  "title": null
}

(添加并行hasTitle: false会令人望而却步,因为我们有许多这样的设置。)

对于 JSON 内容,使用 null 是区分未定义( undefined )和故意省略( null )的非常有用的方法。

您可以允许 null,将 propType 设置为不需要,因为它不是必需的:P

@jquense谢谢,这非常有帮助! 我已经删除了我之前的评论,因为这个 SO答案说了同样的事情。

@jquense您可以允许 null 和 undefined,但不能允许其中之一。

这就是整个问题! Javascript 提供这两种不同的构造是有原因的,因此强制每个人都将null === undefined视为 PropTypes 是一种人为的限制。

仅仅因为我希望 PropType 明确允许 null 并不意味着我也应该允许 undefined 。 它们是两种不同的情况,语言是故意这样设计的。

我有一个公关来解决这个疏忽: https :

我想禁止undefined因为这意味着有一个错字并允许null因为这意味着调用者显式传入null 。 这就是这个问题的重点。 我知道这个问题已经关闭,因为建议只切换到流,我会研究一下。

@binki允许null而不是undefined一种方法是使用您自己的 PropType 验证器函数。

在下面的示例中,仅允许nullstring 。 PropTypes 库在内部使用typeof来检查字符串,所以我也这样做了。 一个好处是您可以将此函数移到组件之外并根据需要调用它。

static propTypes = {
  id: PropTypes.number.isRequired,
  email: function(props, propName, componentName) {
    const propValue = props[propName] // the actual value of `email` prop
    if (propValue === null) return
    if (typeof propValue === 'string') return
    return new Error(`${componentName} only accepts null or string`)
  }
}

我猜这个解决方案偏离了 PropTypes 库的意图 - 我说这是由于以下来自https://github.com/facebook/prop-types/blob/master/factoryWithTypeCheckers.js的 PropTypes 库的代码

在实际验证之前,执行快速检查,其中如果属性值为null则使用 isRequired 设置的属性会自动抛出错误。 换句话说,他们认为必需的属性为 null 是错误的,而我认为它是具有必需的 null 的有效用例。

if (props[propName] == null) {
  if (isRequired) {
    if (props[propName] === null) {
      return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required ' + ('in `' + componentName + '`, but its value is `null`.'));
    }
    return new PropTypeError('The ' + location + ' `' + propFullName + '` is marked as required in ' + ('`' + componentName + '`, but its value is `undefined`.'));
  }
  return null;
} else {
  return validate(props, propName, componentName, location, propFullName);
}

出于上述原因,我同意@jharris4nullundefined 。 将其用作占位符是标准做法。

来自 Mozilla 开发者网络:

值 null 表示有意不存在任何对象值。

null 不是全局对象的属性的标识符,就像 undefined 一样。 相反,null 表示缺乏标识,表明变量不指向任何对象。 在 API 中,通常在可以预期对象但没有相关对象的地方检索 null。

应该允许 null ,至少通过PropTypes.oneOfType([null, PropTypes.string]).isRequired

@jquense — 删除isRequired意味着您可能应该设置默认值。 这是否意味着您现在要为 reducer 中的组件 _and_ 中的初始值设置默认值,所有这些都是为了避免允许null作为 prop 的值?

在等待 API 调用时,我的选择器中有一堆data || ''isRequired接受空字符串'' ,空对象{}等)完成null是告诉组件数据即将到来的完美方式,请稍等! (但我不能那样做...)
@puiu91现在有一个很好的解决方案......我将制作一个实用函数以在我们的代码库中使用......因为看起来这个问题不会很快重新打开叹息

我也同意应该有一种标准方式来接受null作为值,原因与@jharris4@Findiglay所述的相同,但这不再是继续讨论的地方。 此问题不仅已关闭,而且属于facebook/prop-types 。 我正在关注 facebook/prop-types#90 的拉取请求。

撞。 今天仍然遇到这个问题。 拥有对以下内容的内置支持会很棒:

myObj: PropType.object.isRequiredOrNull :)

我认为这方面的优先级非常低。 Flow 是推荐的方法。 http://flow.org/

@Marujah你的片段不正确。

尝试将 null 传递给组件,您会看到会收到警告:

Warning: Failed prop type: The prop 'theProp' is marked as required in 'TheComponent', but its value is null.

问题是 isRequired 首先被评估,它永远不会让 null 或 undefined 值通过。

如果您有兴趣,可以在上面链接用于解决问题的道具类型的 PR。

哦确实! 再次重新测试你是对的

必须通过 PropTypes 绝对允许要求必须明确提供值或空值。

这是我遇到的用例。 我们有一些回调,90% 的选择器都需要这些回调。 少数不需要它们的是非常具体的用例。 我们有一些新开发人员经常忘记提供所有常见的回调。

我想强制所有这些组件的使用做出有意识的决定,不包括特定的回调,而不是某人只是忘记了一些道具。

是的,我们可以通过 flow 进行我们自己更具体的检查,但这将我们的 props 验证分为两个地方,对于浏览 propTypes 定义的人来说是相当不直观的。

只是想在这里添加我的用例。 我有一个包含数据的 redux 存储,以及获取该数据的时间,如果出现错误等。我的组件需要一个“错误”道具(因此如果无法获取数据,它可以向用户显示错误),数据加载成功时为空,出错时填充。

我将加载器组件( PropTypes.node )作为props传递,当我不想渲染加载器时,我传递null
Afaik, render函数在不渲染任何内容时应该返回null而不是undefined 。 因此,将null作为值传递给我看起来是正确的方法。

我正在实现 InputNumber 组件( <input type="number">包装器),所以我有propTypes作为我的道具valuePropTypes.number.isRequired ,当我使用我的组件时,我总是通过它的财产。 但是今天我需要在默认情况下传递一个指向值的可空链接,并且我的组件添加了一个警告。 我能想象到的唯一决定是改变propTypes我的道具valuePropTypes.oneOfType([PropTypes.number, PropTypes.string]) ,并设置defaultProps为空。 但我觉得这不是正确的,因为 input type=number 应该只适用于数字。

我正在尝试执行PropTypes.oneOfType([null, PropTypes.object]).isRequired ,所以无论是 null 还是一个对象,这现在不可能吗?

它需要一个函数: Warning: Invalid argument supplied to oneOfType. Expected an array of check functions, but received null at index 1.

因此,您应该提供一个函数,例如:

PropTypes.oneOfType([
  () => null,
  PropTypes.object
]).isRequired

刚刚遇到这个错误,我写了一个方便的函数来解决它:

function nullable(subRequirement) {
  const check = (required, props, key, ...rest) => {
    if (props[key] === null) {
      return null;
    }
    const sub = required ? subRequirement.isRequired : subRequirement;
    return sub(props, key, ...rest);
  };
  const fn = check.bind(null, false);
  fn.isRequired = check.bind(null, true);
  return fn;
}

用法:

static propTypes = {
  someCallbackFunction: nullable(PropTypes.func).isRequired,
};

在没有isRequired情况下使用nullable是可能的(但毫无意义)。 我使它与isRequired兼容的原因是它可以与react/require-default-props eslint 规则一起使用。

我的用例是一系列符合通用 API 的组件,由处理回调的单个组件包装。 null回调意味着“只读”,因此包装器组件有时会故意传递null s。 同时,重要的是每个属性都传递给子组件,以确保如果添加了一个新属性,它不会被遗漏。 我也不想为符合此 API 的每个组件提供defaultProps的 null; 据他们所知,调用者必须指定一个值。

我把之前写的 helper 和一堆测试一起放在一个包里,以证明正确性:

npm install --save git+https://github.com/davidje13/prop-types-nullable.git#semver:^1.0.0

用法:

import PropTypes from 'prop-types';
import nullable from 'prop-types-nullable';

[...]

static propTypes = {
  thing: nullable(PropTypes.string).isRequired,
};

新解决方案: PropTypes.oneOfType([PropTypes.object]).isRequired

我收到错误。
怎么修。

./~/prop-types/prop-types.js 中的警告关键依赖项:1:482-489 这似乎是一个预先构建的 javascript 文件。 尽管这是可能的,但不建议这样做。 尝试要求原始来源以获得更好的结果。 @ ./~/prop-types/prop-types.js 1:482-489

我正在尝试执行PropTypes.oneOfType([null, PropTypes.object]).isRequired ,所以无论是 null 还是一个对象,这现在不可能吗?

它需要一个函数: Warning: Invalid argument supplied to oneOfType. Expected an array of check functions, but received null at index 1.

因此,您应该提供一个函数,例如:

PropTypes.oneOfType([
  () => null,
  PropTypes.object
]).isRequired

实际上我有一个错误,因为最后是'isRequired',同时为null和required是不兼容的......
这对我有用:

PropTypes.oneOfType([ 
    PropTypes.string.isRequired, 
    () => null 
])

@gugol2请注意,您编写的内容只会完全禁用类型检查(您现在可以将数字传递给该道具,或undefined或任何其他内容); 如果验证成功,您提供的函数应该返回null如果失败则返回非null

如果你想走那条路,你需要更多的东西:

PropTypes.oneOfType([
  PropTypes.string.isRequired,
  (props, key) => props[key] === null ? null : 'Not null'
])

当然,您可以预先定义看起来很糟糕的辅助函数:

const nullable = (props, key) => props[key] === null ? null : 'Not null'

// ...

PropTypes.oneOfType([PropTypes.string.isRequired, nullable])

仅使用PropTypes.oneOfType([PropTypes.string.isRequired])也是非常可能的(但我真的不推荐它!)。 但这感觉像是一个错误,我不希望这样的代码在以后的版本中幸存下来。 另请注意,它与先前建议的不起作用的


如果你能等一下,有一个公开的 PR ,它的进展非常缓慢,但显然仍在考虑中。

在 PR 合并之前,我建议使用我创建它背后.isRequired放在行尾,这使得它与 linting 规则兼容。

恕我直言,这是正确的行为,但应该记录下来。

我看到的一个常见用例是 React 在对数据的 API 调用完成之前渲染组件。 例如,第一个渲染将渲染一个项目列表 ( items: null )。 然后 API 调用完成,现在items填充了一个数组。

有什么最好的方法来处理这个吗? 我希望这个道具是必需的,但在我从 API 取回它之前它是空的。

PropTypes.oneOfType([
  PropTypes.string.isRequired,
  (props, key) => props[key] === null ? null : 'Not null'
])

@davidje13我在使用这种方法时遇到了一个小问题。 覆盖测试有 1/4 的情况从未被覆盖。

假设我有一个组件 Login,它只有一个 prop 'name' 可以为 null 或需要一个字符串:

const Login = ({name}) => {
  return <div>{name}</div>
} 

所以它的proptypes是:

Login.propTypes = {
  name: PropTypes.oneOfType([
    PropTypes.string.isRequired,
    (props, key) => (props[key] === null ? null : 'Not null'),
  ]),
};

当我测试这个组件时,我真的只有 2 个场景,空或一个必需的字符串。

render(<Login name={null} />
render(<Login name={'anyName'} />

但是覆盖率告诉我我的测试只有 75% 的覆盖率。
我想知道对此的官方方法是什么。

听起来您缺少的测试用例是它未通过道具检查的测试用例吗? 即,如果您传递一个数字或未定义或其他不应该有的东西。

听起来您缺少的测试用例是它未通过道具检查的测试用例吗? 即,如果您传递一个数字或未定义或其他不应该有的东西。

不,不是那样。

传递 undefined 不会扩大覆盖范围。
而且我无论如何都不能传递数字,这不是允许的值。

我无法涵盖这种情况。

此页面是否有帮助?
0 / 5 - 0 等级

相关问题

kib357 picture kib357  ·  103评论

fdecampredon picture fdecampredon  ·  139评论

gabegreenberg picture gabegreenberg  ·  264评论

iammerrick picture iammerrick  ·  94评论

AdamKyle picture AdamKyle  ·  148评论