从componentWillReceiveProps迁移

时间:2019-11-29 16:04:58

标签: reactjs

我正在尝试在react中构造一个错误边界,如下所示:-

import React, { Component } from 'react';

type ErrorBoundaryProps = {
    fallBackComponent: React.ReactElement;
    resetState?: boolean;
}

type ErrorBoundaryState = {
    hasError : boolean;
}

export class ErrorBoundary extends Component<ErrorBoundaryProps, ErrorBoundaryState> {
    state = {hasError: false};

    static getDerivedStateFromError( ){
        return { hasError : true};
    }

    componentWillReceiveProps( newProps : ErrorBoundaryProps ){
        if(newProps.resetState){
            this.setState({hasError:false})
        }
    }
    render(){
        const {fallBackComponent, children} = this.props;
        if(this.state.hasError){
            return fallBackComponent;
        }
        return children;
    }
}

使用“ resetState”道具的基本思想是,如果父道具改变,则强制错误边界尝试再次渲染子级。如果新道具仍然导致错误,它将返回到后备用户界面。因此,使用componentWillRecieveProps会强制在每次更改道具时hasError为false,并且错误边界会尝试呈现子组件。

调用它的父组件如下:-

import React, { useState } from 'react';
import {ErrorBoundary} from './ErrorBoundary';

const ErrorChild = ( { hasError } : {hasError : boolean}) => {
  if(hasError){
    throw new Error("Dummy error");
  }
  return <>Actual screen</>
}
const App: React.FC = () => {
  const [error, setError] = useState(false);
  return (
    <div className="App">
      <button onClick={() => setError((previousState) => !previousState)}>Toggle error</button>
      <ErrorBoundary fallBackComponent={<>Fallback Screen</>} resetState>
        <ErrorChild hasError={error} />
      </ErrorBoundary>
    </div>
  );
}

export default App;

这基本上呈现了一个按钮,后面是实际的组件。单击按钮可切换错误状态,即孩子是否抛出错误。当“ resetState”道具为true时,我可以在“后备屏幕”和“实际屏幕”之间切换。当“ resetState”为false时,一旦呈现“后备屏幕”,则在再次切换时将不呈现“实际屏幕”。

如何在不使用componentWillRecieveProps的情况下实现相同的功能?

我尝试使用getDerivedStateFromProps,但事实证明,此函数在每次渲染之前都会调用,不仅是在props更改时调用,还可以在捕获错误并卸载整个DOM后有效地重置错误边界的状态。 。 其他技术建议使用由错误边界的父组件更改的“键”来强制重置错误边界。这对我不太感兴趣,因为我试图将其保留为可重复使用的组件,并且我不希望该组件的用户负责处理密钥更新。

还有其他方法可以实现吗?

我的基本要求是,如果对孩子的道具的更改不再引起错误,则错误边界应向孩子显示。

0 个答案:

没有答案