我正在开发React应用程序,这是我用于组件的方法:我使用PropTypes验证来验证希望收到的道具,但是我仍然分配默认值以避免它如果接收到的数据出现问题,则中断。
最近有人告诉我,我们不应该这样做,因为道具是我们希望父母给予的,并且如果不遵守合同规定的话,则可能会破坏组件。
哪种方法是正确的,优缺点是什么?
我的一些考虑值得深思。
按照我最初的方法,在测试中,我显式测试传递给被测组件的默认值,这些默认值会传递一些无效数据,并期望仍然打印出有效快照。测试不会由于某些不良数据而失败,但是我会打印出PropTypes验证警告(如果需要,我可以将其转换为错误-
我想-或在测试中将其模拟出来时保持沉默)。
在测试和实际应用程序中,这些警告都更加简洁明了,而不是仅仅看到一个错误消息,即“无法从未定义中读取’someProp’”或类似错误(并让React渲染周期中断)。propType验证可以直接清楚地告诉您您做错了什么(您以错误的方式传递了prop,prop完全丢失,等等)。
相反,使用第二种方法会因为应用程序中断而导致测试失败。我认为,只有在测试覆盖率非常好(90/100%)的情况下,这才是一个好方法,否则会带来风险-
它可能会上线并在极端情况下中断,从而破坏产品声誉。重构或需求更改经常发生,并且某些极端情况可能导致不希望的数据中断应用程序,并且没有在自动或手动测试中捕获。
这意味着,当应用程序处于活动状态时,由于某些错误的数据,代码可能会中断父组件,并且整个应用程序将停止工作,而在第一种情况下,应用程序是有弹性的,并且仅以受控方式显示一些空白字段。
有什么想法吗?
遵循一个简化的示例:
import React from 'react';
import PropTypes from 'prop-types';
import styles from './styles.css';
export const App = ({ person : { name, surname, address, subscription } = {} }) => (
<div style={styles.person}>
<p> {person.name} </p>
<p> {person.surname} </p>
<p> {person.address} </p>
<div>
{
person.subscription &&
<Subscription details={person.subscription} />
}
</div>
</div>
);
// PS. this is incorrect in this example (as pointed out in an answer). Real code used inline initialization.
// App.defaultProps = {
// person: { subscription: undefined },
// };
App.propTypes = {
person: PropTypes.shape({
name: PropTypes.string.isRequired,
surname: PropTypes.string.isRequired,
address: PropTypes.string,
subscription: PropTypes.object,
}).isRequired,
};
import React from 'react';
import { shallow } from 'enzyme';
import { mockOut } from 'testUtils/mockOut';
import { App } from '../index.js';
describe('<App>', () => {
mockout(App, 'Subscription');
it('renders correctly', () => {
const testData = {
name: 'a name',
surname: 'a surname',
address: '1232 Boulevard Street, NY',
subscription: { some: 'data' },
}
const tree = shallow(<App person={testData} />);
expect(tree.html()).toMatchSnapshot();
});
it('is resilient in case of bad data - still generates PropTypes validation logs', () => {
const tree = shallow(<App person={undefined} />);
expect(tree.html()).toMatchSnapshot();
});
});
更新:
该问题的主要重点在于将默认值分配给标有isRequired的道具是否正确(而不是让它们的缺失破坏组件)
最近有人告诉我,我们不应该这样做,因为道具是我们希望父母给予的,并且如果不遵守合同规定的话,则可能会破坏组件。
的确,如果component中的props是可选的,则应由component(呈现实际视图的组件)而不是父组件处理。
但是,您可能会遇到以下情况:如果任何子组件合同中断,则父级应中断。我可以想到两种可能的方式来处理这种情况-
将错误通知程序传递给子组件,如果出现任何错误,子组件可以将错误报告给父组件。但这不是一个干净的解决方案,因为如果有N个孩子,并且如果有多个孩子会中断(或向父母报告错误),那么您将毫无头绪,也将很难管理。当我学习React时,我通常会遵循这个:
try/catch
在父组件中使用而不盲目地信任任何子组件,并在出现问题时显示错误消息。try/catch
在所有组件中使用时,如果未履行任何合同,则可以安全地从组件中引发错误。
哪种方法是正确的,优缺点是什么?
IMO,第二种方法(try/catch
在组件和未满足要求时抛出错误)是有效的,它将解决所有问题。在未通过道具的情况下编写组件的测试时,加载组件时可能会出现错误。
更新资料
如果您使用React> 16,这是处理错误的方法。
在 AWS 上创建弹性豆茎应用程序失败,运行状况显示灰色,错误如下,我无法继续。 警告:环境健康已被设置为红色 错误:当组资源中没有ELB时,无法更新ELB目标组 错误:创建名为awseb-e-securitygroupname-stack-AWSEBSecurityGroup-THEIDOFYOURSECURTYGROUP的安全组失败原因:资源创建已取消 错误:名为“awseb-e-somena
我对Amazazon Web服务提供的弹性IP服务的使用有点困惑。我想主要的想法是,按照以下简单的过程,我可以切换到web应用程序的新版本,而不会停机: null 抱歉,如果有些问题听起来很愚蠢,但我只是一个程序员,这是我第一次建立云系统。 谢谢!
我正在工作一个AWS弹性Beanstalk应用程序,上传文件到AWS S3桶。Beanstalk应用程序是一个.NET Core Web API应用程序,我遵循了本指南(http://docs.aws.amazon.com/sdk-for-net/v3/developer-guide/net-dg-config-netcore.html),并且在磁盘上有一个凭据文件,用于本地开发,其中有我的共享访
问题内容: 我有一个Angular应用程序,我想在ReactJS中编写应用程序的某些部分。 如何将ReactJS应用程序注入现有的Angular应用程序中?我还需要组件的双向通信。 问题答案: 您可能需要其他选项,所以我在第2段中编写了它: 无需通信的Angular-ReactJS 具有双向通信的Angular-ReactJS 下面的所有代码都是最少的,无法在提出的步骤中显示问题。在GitHub上
问题内容: 我在徘徊自己是哪个组件最适合显示swing中的快速搜索结果。我想创建类似这样的内容,在用户可以输入文本的地方创建一个文本字段,在输入过程中,我将改善对数据库的后端快速搜索,并且希望在文本框下方显示数据,他将能够浏览结果,然后按输入将在表中显示结果。所以我的问题是,是否有任何组件已经具有此显示逻辑?还是不是,实现它的最佳方法是什么。 如果可以在桌面应用程序上进行,此搜索将是ajax在网络
我正在用Swift编写一些性能关键的代码。在实现了我能想到的所有优化,并在仪器中分析了应用程序之后,我意识到绝大多数CPU周期都花在了对浮点数组执行和操作上。因此,为了看看会发生什么,我用良好的老式循环替换了和的所有实例。令我吃惊的是...循环要快得多! 的平均执行时间:20.1秒。循环的平均执行时间:11.2秒。使用整数而不是浮点的结果是相似的。 我创建了一个类似的基准测试Swift的的性能。这