首页 > 解决方案 > React:防止子组件在获取数据之前进行渲染

问题描述

我正在尝试制作一个包装器组件来显示加载微调器、错误消息或子组件,具体取决于是否在 React 中获取了数据。然而,即使页面正在加载(this.state.loading === true)意味着不应该渲染子内容,React 仍然以某种方式渲染或处理子组件,并且会抛出错误Cannot read property 'useRoundedImages' of undefined

// page.js
export default class Page extends Component {
    constructor(props) {
        super(props)
        this.state = {
            loading: true,
            error: undefined,
            user: undefined,
        };
    }
    componentDidMount() {
        getData(...).then(res => {
            this.setState({ loading: false, user: res.data.user});
        });
    }
    render() {
        return (
            <LoadWrapper loading={this.state.loading} error={this.state.error}>
                <p>{this.state.user.options.useRoundedImages}</p>
            </LoadWrapper>
            );
        }
    }
}

// loading-wrapper.js
export default class LoadWrapper extends Component {
    render() {
        return (
            this.props.loading ? <Spinner animation="border" className="mx-auto d-block" /> :
                this.props.error ? <ErrorPage error={this.props.error}></ErrorPage> :
                    <>{this.props.children}</>
        );
    }
}

如何防止渲染这些元素,或者有更好的方法有条件地渲染我的加载微调器、错误消息和子组件?

标签: reactjs

解决方案


我认为问题来了:

<LoadWrapper loading={this.state.loading} error={this.state.error}>
        <p>{this.state.user?.options.useRoundedImages}</p>
</LoadWrapper>

这里的问题是Page组件内部的每一行。你的LoadWrapper逻辑是正确的。但是,当您Page的组件渲染时,它会出现在每一行中,因此这意味着您的LoadWrapper遗嘱不会生成子组件,但您的Page组件会出现在每一行中,这就是它给出此错误的原因,因为当时没有任何user价值。Cannot read property 'useRoundedImages' of undefined. 您可以使用可选链接来防止这种情况

在这里,我复制了您的逻辑并创建了 POC。希望您了解上下文:代码:

import React, { Component } from "react";
import "./styles.css";

class LoadWrapper extends Component {
  render() {
    if (this.props.loading) {
      return <>Loading...</>;
    } else if (this.props.error) {
      return <>Error....</>;
    } else {
      return <>{this.props.children}</>;
    }
  }
}

class Page extends Component {
  constructor(props) {
    super(props);
    this.state = {
      loading: true,
      error: undefined,
      user: undefined
    };
  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({
        loading: false,
        user: {
          options: {
            useRoundedImages: "test"
          }
        }
      });
    }, 2000);
  }
  render() {
    return (
      <LoadWrapper loading={this.state.loading} error={this.state.error}>
        <p>{this.state.user?.options.useRoundedImages}</p>
      </LoadWrapper>
    );
  }
}

export default function App() {
  return (
    <div className="App">
      <h1>Hello CodeSandbox</h1>
      <h2>Start editing to see some magic happen!</h2>
      <Page />
    </div>
  );
}

这是演示:https ://codesandbox.io/s/thirsty-water-mgwp2?file=/src/App.js:0-1078


推荐阅读