ReactJS应用程序-弹性VS快速失败 [英] ReactJS Application - resiliency VS failing fast

查看:88
本文介绍了ReactJS应用程序-弹性VS快速失败的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在开发React应用程序,这是我用于组件的方法:我使用PropTypes验证来验证我希望收到的道具,但是我仍然分配默认值以便避免在接收到的数据出问题的情况下中断它.

I'm in the middle of the development for a React application and this is the approach I used for my components: I validate the props that I expect to be received using the PropTypes validation but I still assign default values in order to avoid that it breaks if something goes wrong with the received data.

最近有人告诉我,我们不应该这样做,因为道具是我们对父母的期望,并且如果不遵守合同规定的话,也会破坏道具.

Recently I've been told that we should not do that, that the props are what we expect from the parent and if the contract is not respected to let the component break.

哪种方法正确,利弊何在?

我的一些想法值得深思.

按照我最初的方法,在测试中,我明确测试传递给被测组件的默认值,这些默认值会将一些无效数据传递给您,并期望仍然打印出有效快照. 测试不会由于某些不良数据而失败,但是我会打印出PropTypes验证警告(如果需要,我可以将其转换为错误-我想-或可以在测试中将它们模拟出来而保持沉默).

Following my initial approach, in the tests I explicitly test default values passing to the component under test some invalid data and expecting a valid snapshot to be still printed out. The tests don't fail due to some bad data but I print out the PropTypes validation warnings (that could though be transformed in errors if wanted - I think - or be silenced mocking them out in the test).

这些警告在测试和实际应用程序中都更加简洁明了,而不仅仅是看到错误消息无法从中读取'someProp' undefined"或类似的代码(并让React渲染周期中断).propType验证直接清晰地告诉您您做错了什么(您以错误的类型传递了prop,prop完全丢失,等等).

These warnings both in the tests and in the real application are more concise and clear than just seeing an error saying "cannot read 'someProp' from undefined" or similar (and letting React render cycle break). The propType validations directly and clearly tell you what you did wrong (you passed in the wrong type as prop, the prop was missing completely, etc).

使用第二种方法,但由于应用程序中断,测试失败.我认为,只有在测试覆盖率非常好(90/100%)的情况下,这才是一个好方法,否则会带来风险-它可能会上线并在极端情况下中断,从而破坏产品声誉. 重构或需求变更经常发生,某些极端情况最终可能会导致不想要的数据中断应用程序,并且无法在自动或手动测试中捕获.

Using the second approach instead the tests fail because the app breaks. I think that this is a good approach only if the test coverage is really good (90/100%) otherwise it's a risk - it could go live and break on edge cases ruining the product reputation. Refactoring or requirements changes happen quite often and some edge cases could end up with undesired data that break the application and was not captured in automated or manual tests.

这意味着,当应用程序处于活动状态时,由于某些错误的数据,代码可能会中断父组件,并且整个应用程序都将停止工作,在第一种情况下,应用程序具有弹性并仅显示 一些空字段以受控的方式.

This means that when the application is live the code could break in a parent component due to some bad data and the whole application stop working, where instead in the first case the app is resilient and simply displays some empty fields in a controlled way.

有想法吗?

下面是一个简化的示例:

Follows a simplified example:

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的道具分配默认值是否正确(而不是让其缺席破坏该组件)

推荐答案

最近有人告诉我,我们不应该这样做,因为道具是 我们对父母的期望,以及如果不遵守合同 让组件损坏.

Recently I've been told that we should not do that, that the props are what we expect from the parent and if the contract is not respected to let the component break.

确切地说,如果component中的props是可选的,则应由呈现实际视图的component(而不是父组件)来处理.

Exactly, if a props in component is optional, component(who renders the actual view) should handle that, not the parent component.

但是,您可能会遇到以下情况:如果任何子组件合同中断,则父级应中断.我可以想到两种可能的方式来处理这种情况-

However, you can have a situation where the parent should break if any of the child components contract is breaking. I can think of two possible way to handle this situation-

  1. 将错误通知程序传递给子组件,如果出现任何错误,子组件可以将错误报告给父组件.但这不是一个干净的解决方案,因为如果有N个孩子,并且如果有多个孩子会中断(或向父母报告错误),那么您将毫无头绪,也将难以管理.在学习React时,我通常会遵循此规则:P]

  1. Passing error notifier to child components, where if anything goes wrong child can report error to parent component. But this is not clean solution because if there are N child and if more than one will break(or report error) to parent, you will have no clue and will be hard to manage.[This is not effective at all but wrote here because I used to follow this when I was learning React :P]

在父组件中使用try/catch,不要盲目地信任任何子组件,并在出现问题时显示错误消息.在所有组件中使用try/catch时,如果未履行任何合同,则可以安全地从组件中引发错误.

Using try/catch in parent component and not trust any child component blindly and show error messages when something goes wrong. When you are using try/catch in your all component, you can safely throw error from the components when any contract is not fulfilled.

哪种方法正确,利弊何在?

Which approach is correct and what are the pros and cons?

IMO,第二种方法(组件中的try/catch和未满足要求时引发错误)是有效的,它将解决所有问题.在未通过道具的情况下为组件编写测试时,加载组件时可能会出现错误.

IMO, the second approach(try/catch in components and throwing error when requirements are not fulfilled)is valid and will solve all the issues. While writing tests for component when props are not passed you can expect an error when loading the component.

如果您使用的是React> 16,则这里是处理错误的方法.

If you are using React > 16, here is the way to handle errors.

这篇关于ReactJS应用程序-弹性VS快速失败的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆