【问题标题】:React component doesn't re-render after state changeReact 组件在状态更改后不会重新渲染
【发布时间】:2019-04-06 01:05:08
【问题描述】:

我从父容器接收道具,并在子组件中使用 Carousel 来显示图像。我的代码如下所示:

import React, { Component } from "react";
import ReactDOM from "react-dom";
import style from './ReactSlick.less';
import Carousel from 'nuka-carousel';

export default class ReactSlick extends Component {

  constructor(props) {
    super(props);
    this.state = {
      slides:this.props.pictureArray,
    };
  }}

renderImages() {
 return this.state.slides.map(slide => {
    return (
      <div  key={slide._id}><img src = {slide.image} /></div>
    );
  }, this);
}

return (
  <div className = {style.container}>
      <Carousel autoplay={true}>
        {this.renderImages()}
      </Carousel>
  </div>
);
}}

我基本上已经尝试了所有我能想到的方法,包括在 componentDidMount 中初始化东西。使用条件渲染来检查数组的长度并仅在存在任何内容时显示。图片数组是一个数组,其中包含我想在轮播中显示的带有 id 的图像。我像这样从父容器中获取它:

getImage= (key)=> {
            let {getImage} = this.props;
            let codeArray = [];
        for (let i = 0; i < getImage._id.length; i++) {
             api(getImage._id[i])
            .then(res => codeArray.push(res)),
            (error => console.log(error));}

        return (
            <Bubble
                key={key}
                side="left"
                onImageClick={this.handleLogoClick}>
                <ReactSlick pictureArray={codeArray} />
                </Bubble>
        );
    }

当它进入子组件时数据已经存在,我也通过在构造函数中将其注销来仔细检查它。我尝试将 API 放入 componentDidMount 并在子组件中设置状态,但这也不起作用。

我已经测试了我从本地 API 获取的相同数据,并且似乎可以从 JSON 中工作,但是当我从远程服务器获取它时它不起作用。它显示来自服务器的数据的唯一时间是当我对代码进行更改并且它主动重新加载然后不知何故数据在那里可见但不是第一次。

我认为组件不会重新渲染或其他什么。有没有办法对子组件进行强制刷新以使其工作?我读过的答案说,当 setState 被调用时,它会自动触发重新渲染,但在我的情况下似乎没有任何效果。

【问题讨论】:

  • 将此this.state.slides.map 更改为this.props.pictureArray.map。你不需要这个状态
  • 也试过了,还是不行。这就是为什么我指定它可能会重新渲染但没有运气。
  • 当我在页面上放置一个按钮并且单击该按钮时运行 forceUpdate() 时,这似乎起作用了。有什么方法可以在渲染后 1 秒自动运行此方法?
  • 你能告诉我们如何重新设置父母的pictureArray吗?同样使用native for loop 几乎总是不如.map or .forEach, etc
  • 它在我提供的代码中。我正在拍摄图片数组并将其设置为子组件状态的幻灯片。我正在使用 for 循环将数据推送到父容器中的代码数组中,因此当数据被推送到子容器时,数据肯定已经准备就绪。

标签: javascript reactjs rendering carousel


【解决方案1】:

问题在于您对asynchronous 代码进行迭代的方式。由于您试图通过 async api 调用 在循环中填充 codeArray,因此您不能使用 for loop 否则 getImage 将不会等待您的 api 调用解决并因此在 @ 时立即返回987654325@ 仍然是空的。因此,请使用其他类型的迭代器,例如可以与 async code 一起使用的 .map

这可能会对您有所帮助,请查看:Using async/await with a forEach loop

/* So this doesn't work */
for (let i = 0; i < getImage._id.length; i++) {
  api(getImage._id[i]).then(res => codeArray.push(res)), (error => console.log(error));
}



/* Need to find a way to wait for all `api(getImage._id[i]).then` calls
   to finish first, only then should `getImage()` return.
   And also take not I am placing `codeArray` in the parent's state */


async getImage () {
  let codeArray = []; // just set the scope using let

  await Promise.all(this.props.images.map(async (image) => {
    codeArray = await api(getImage._id[i]);
  }));

  this.setState({ codeArray })
}

我建议在组件确实挂载时调用getImage

async componentDidMount() {
  await this.getImage();
}

最后在您的render 方法中: &lt;ReactSlick pictureArray={this.state.codeArray} /&gt;

/* also set your component statecodeArrayas an empty array to be safe */

P.S:我假设 images 已经从父母的道具设置(但它也可能处于状态)。如果 images 将有 10 个项目,并且 api() 调用需要 1 秒才能完成,因此 getImage() 将需要大约 10 seconds 然后调用 setState 或更新您的组件(以及子 ReactSlick

希望对你有帮助

【讨论】:

    【解决方案2】:

    你有现有的props,为什么要使用state 来迭代循环?另一种解决方案是使用self-route。所以只要 API 成功获取数据。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 2021-05-19
      • 2022-01-26
      • 2019-06-29
      • 2019-02-27
      • 2018-03-17
      相关资源
      最近更新 更多