Ga *_*chi 9 testing validation reactjs resiliency
我正处于React应用程序开发的中间,这是我用于组件的方法:我使用PropTypes验证验证我希望收到的道具,但我仍然分配默认值以避免它如果收到的数据出现问题,则会中断.
最近我被告知我们不应该这样做,道具是我们对父母的期望,如果合同没有得到尊重让组件破裂.
哪种方法是正确的,有哪些优点和缺点?
我的一些考虑因素值得深思.
在我的初始方法之后,在测试中,我明确地测试了传递给测试组件的默认值,一些无效数据并期望仍然打印出有效的快照.由于一些不良数据,测试不会失败,但是我打印出PropTypes验证警告(如果需要,可能会转换为错误 - 我认为 - 或者在测试中嘲笑它们).
测试和实际应用程序中的这些警告比仅仅看到"无法读取'someProp'未定义"或类似的错误(以及让React渲染循环中断)更简洁明了.propType验证直接并清楚地告诉你你做错了什么(你传给了错误的类型作为道具,道具完全缺失等等).
使用第二种方法,测试失败,因为应用程序中断.我认为只有当测试覆盖率真的很好(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,
};
Run Code Online (Sandbox Code Playgroud)
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();
});
});
Run Code Online (Sandbox Code Playgroud)
更新:
问题的主要焦点在于是否将默认值分配给标记为isRequired的道具(而不是让它们的缺席破坏组件)是否正确
最近我被告知我们不应该这样做,道具是我们对父母的期望,如果合同没有得到尊重让组件破裂.
确切地说,如果组件中的props是可选的,则组件(呈现实际视图的人)应该处理它,而不是父组件.
但是,如果任何子组件合同中断,则父级应该中断.我可以想到两种可能的方法来处理这种情况 -
将错误通知程序传递给子组件,如果出现任何问题,则子级可以向父组件报告错误.但这不是一个干净的解决方案,因为如果有N个孩子并且如果有多个孩子会破坏(或报告错误)给父母,你将毫无头绪并且难以管理.[这根本没有效果,但写在这里是因为当我学习React时我常常遵循这个:P]
try/catch
在父组件中使用,不要盲目地信任任何子组件,并在出现问题时显示错误消息.try/catch
在所有组件中使用时,如果未满足任何合同,则可以安全地从组件中抛出错误.
哪种方法是正确的,有哪些优点和缺点?
IMO,第二种方法(try/catch
在未满足要求时的组件和抛出错误)是有效的,并将解决所有问题.在没有传递道具时编写组件测试时,加载组件时可能会出现错误.
如果您使用React> 16,这是处理错误的方法.
归档时间: |
|
查看次数: |
592 次 |
最近记录: |