微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

关于 componentDidCatch 中 setState 的未来弃用警告

如何解决关于 componentDidCatch 中 setState 的未来弃用警告

原始问题:如果在渲染阶段发生多个错误,如何避免在错误边界内压制其中一些错误

我的困惑有两个方面:

  1. componentDidCatch 应该在提交阶段被调用,并且明确允许副作用。我原以为它在以下示例中为 would only fire once,但它会触发两次。这实际上很有帮助,因为它允许暂时将其用作修复程序,但我仍然想了解原因。

  2. react docs 状态下的注释

如果出现错误,您可以通过调用 setState 使用 componentDidCatch() 呈现后备 UI,但这将在未来版本中弃用。改用静态 getDerivedStateFromError() 来处理回退渲染。

这使我将来能够想到的存储多个错误的唯一解决方案无效。
遗憾的是,getDerivedStateFromError does not have access to state


以下只是演示当前行为的示例。当在 setState 中取消注释 componentDidCatch 时,我得到了一个可行的解决方案,但是遇到了上述问题。

let countStatic = 0;
let countInstance = 0;
let actualThrows = 0;
const errorComponentGenerator = n => () => { actualThrows++; throw n; };
const One = errorComponentGenerator(1);
const Two = errorComponentGenerator(2);
class Boundary extends React.Component {
  state = { hasError: false,errors: [] };
  errors = [];
  static getDerivedStateFromError(error) {
    // expected: two times
    console.log('getDerivedStateFromError called')
    countStatic++;
    return { hasError: true,error };
  }
  
  componentDidCatch(error,errorInfo) {
    // expected: once,got twice
    console.log('componentDidCatch called')
    countInstance++;
    // Would help,but is discouraged by react docs
    // this.setState(state => ({ hasError: true,errors: [...state.errors,error] }));
    this.errors.push(error);
  }
  
  render() {
    if (this.state.hasError)
      return (
          `static: ${countStatic},instance: ${countInstance},actual: ${actualThrows}\n`
        + `Errors - length: ${this.errors.length}\n`
        + `${JSON.stringify(this.errors)}`
      );
    return (
      <React.Fragment>
        <One />
        <Two />
      </React.Fragment>
    );
  }
}

const boundaryInstance = React.createRef();
ReactDOM.render(<Boundary ref={boundaryInstance} />,document.getElementById('app'));
setTimeout(
  () => console.log(
      `afterwards instance: ${countInstance}\n`
    + `${JSON.stringify(boundaryInstance.current.errors)}`
  ),2000
);
div { white-space: pre-wrap; }
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>

<div id="app"></div>

PS:我现在忽略了弃用警告,并采用了“很好用”的策略,但这不是一件好事。也许弃用警告只是意味着“不要更改在 componentDidCatch 中切换到回退的状态”?我想我会看到,当弃用发生时......

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。