如果尚未从状态加载项目,则阻止渲染尝试

prevent render attempt if item not loaded from state yet

我正在请求来自 cloudinary 的图像,从表面上看,一切似乎都很好,因为我可以按预期在前端看到图像。但是在查看 chrome 开发工具时,我可以看到首先出现了一个 404 错误,它显示了对存储图像但没有图像名称的路径的调用。对于成功的第二次调用,有路径和图像名称。

因此,从第一次请求时的状态来看,图像名称似乎尚未加载。我确实尝试了 && 条件检查,但结果相同,即:

{this.state.bgImg && this.state.bgImg}

然后我尝试了:

{this.state.bgImg ? this.state.bgImg : "fakeImage.jpg"}

在开发工具中,我看到它实际上试图获得 fakeImage.jpg

我怎样才能避免这种情况?

class Home extends Component {
  state = {
    title: "",
    bgImg: "",
    categories: []
  };

  async componentDidMount() {
    const response = await getHero();
    const { data: categories } = await getCategories();
    this.setState({
      title: response.data.title,
      categories,
      bgImg: response.data.bgImg
    });
  }

  render() {
    return (
      <React.Fragment>
        <NavBar />
        <Hero
          title={this.state.title}
          bgImg={this.state.bgImg && this.state.bgImg}
        />
      </React.Fragment>
    );
  }
}
export default Home;


const imageUrl = process.env.REACT_APP_CLOUDINARY_URL;

class Hero extends Component {
  render() {
    const { title, bgImg } = this.props;
    return (
      <section
        className="section-hero d-flex justify-content-center align-items-center mb-5"
        style={{
          backgroundImage: `linear-gradient(rgba(0, 0, 0, 0.2), rgba(0, 0, 0, 0.2)), url(${imageUrl}/somepath/${bgImg})`

        }}
      >
        <Container className="text-center text-white">
          <h1>{title}</h1>
        </Container>
      </section>
    );
  }
}
export default Hero;

对于 Home 组件的初始渲染,您将一个空字符串传递给 Hero 作为 bgImg 属性。您将收到 404 错误,因为在此路径中找不到图像。

url(${imageUrl}/somepath/${bgImg}) <--- bgImg is an empty string on first render.

要解决此问题,您可以只进行条件检查,以便您的 Hero 组件仅在 Home 中的 bgImg-state 为真值时呈现,它将在componentDidMount.

中完成的提取

因此,对于第一个渲染,我们将为 bgImg 提供默认值 null(这是有道理的),因为没有值。 Hero 组件还不会被使用(所以没有 404 错误)。然后在 componentDidMount 之后,一切都会按预期进行。

class Home extends Component {
  state = {
    title: "",
    bgImg: null,
    categories: []
  };

  async componentDidMount() {
    const response = await getHero();
    const { data: categories } = await getCategories();
    this.setState({
      title: response.data.title,
      categories,
      bgImg: response.data.bgImg
    });
  }

  render() {
    const { bgImg } = this.state
    return (
      <React.Fragment>
        <NavBar />
        { bgImg && (
           <Hero
              title={this.state.title}
              bgImg={bgImg}
           />
        )}
      </React.Fragment>
    );
  }
}
export default Home;