当您在异步调用的构造函数中使用 setState 时,为什么此组件不会更新 - ReactJS/ReactNative?

Nis*_*ula 3 javascript constructor setstate reactjs react-native

** 编辑/重新措辞 **

在对我的问题进行了一些很好的回答之后,我编辑了问题中的代码,以尽可能清楚地说明我不明白的内容。

我有一个 withErrorHandler ,它将用作许多独立组件的 hoc 。

其中一个组件是 MyComponent。

withErrorHandler 的 componentWillMount 中的代码按预期工作,但由于它是一个废弃的方法,我必须将它移到某个地方。

位置 - ComponentDidMount 拦截器将无法拦截错误。

位置 - 构造函数拦截器将拦截错误,但不会向用户显示 withError 处理程序中的 Modal。

这里到底发生了什么?

import React from 'react';
import Modal from '../../components/UI/Modal/Modal';
import Aux from '../Aux/Aux';

const withErrorHandler = (WrappedComponent, axiosInstance) => {
    return class extends React.Component {
        constructor(props) {
            super(props);
            this.state= {
                error: null
            };
        }
        
        componentWillMount() {
            let { request, response} = axiosInstance.interceptors;
            this.requestInterceptor = request.use(req => {
                this.setState({error: null});
                return req;
            })
            this.responseInterceptor = response.use(resp => resp, error => {
                console.log("axiosInstance Intercepted Error\t",error)
                this.setState({error})
            })
        }

        componentWillUnmount() {
            let { request, response} = axiosInstance.interceptors;
            request.eject(this.requestInterceptor);
            response.eject(this.responseInterceptor);
        }

        errorConfirmedHandler = () => {
            this.setState({error: null})
        }

        render() {
            return <Aux>
                <Modal show={this.state.error} modalClosed={this.errorConfirmedHandler}>
                    {this.state.error ? this.state.error.message : null}
                </Modal>
                <WrappedComponent {...this.props} />
            </Aux>
        }
    }
}

export default withErrorHandler;
Run Code Online (Sandbox Code Playgroud)
import React, { Component } from 'react';
import axiosInstance from '../../AxiosInstance';
import Spinner from '../../components/UI/Spinner/Spinner';
import withErrorHandler from '../../hoc/withErrorHandler/withErrorhandler';

class MyComponent extends Component {

    constructor(props) {
        super(props);
        this.state = {
            ingredients: null,
            error: false
        }
    }

    componentDidMount() {
        // Deliberately placed Error in 'ingredients.json' by removing n
        axiosInstance.get('ingredients.jso').then(response => {
            this.setState({
                ingredients: response.data
            })
        }).catch(error => {
            console.log(`Unable to load Ingredients\nError:\t${JSON.stringify(error, null, 2)}`)
            this.setState({ error: true})
        })
    }

    render() {
        return (
                this.state.ingredients ?
                    <p>show ingredients</p> :
                    this.state.error ? <p>Ingredients Can't be loaded</p> : <Spinner />
        );
    }
}

export default withErrorHandler(MyComponent, axiosInstance);
Run Code Online (Sandbox Code Playgroud)

map*_*pie 5

您不应该在 中执行任何副作用 constructor ,它基本上应该用于初始化本地状态(和其他变量)或与内容绑定的函数。

其次,在反应中,您应该小心使用以下方法,因为它们在服务器和客户端上都被调用。

  1. constructor
  2. componentwillmount (已弃用)
  3. getderivedstatefromprops

更好的方法是在componentDidMount生命周期方法中更新状态。该方法将在组件的整个生命周期中触发一次。

class Component1 extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      result: null,
    };
    this.fetchResult = this.fetchResult.bind(this)
  }

  componentDidMount() {
    this.fetchResult()
  }

  fetchResult () {
    axiosInstance
      .get(url)
      .then((result) => {
        console.log("result", result);
        this.setState({ result });
      })
      .catch((error) => {});
  }

  render() {
    return (
      <>
        <h1>SomeText</h1>
        <p>{this.state.result ? "Hey, I got the result" : "Waiting..."}</p>
      </>
    );
  }
}
Run Code Online (Sandbox Code Playgroud)