首页 > 解决方案 > 如何重置已安装组件中道具更改的状态?

问题描述

我有一个<BlogPost>组件可能是无状态函数组件,但由于以下原因变成了类有状态组件:

它呈现的 blogPost 项目(接收为props)在其 html 标记的内容中嵌入了图像,我使用marked库对其进行解析并呈现为博客文章,其段落之间有图像,h1、h2、h3 等。

事实是我需要在将帖子内容呈现给我的客户之前预加载这些图像。我认为如果你开始阅读一个段落并且突然向下移动 400 像素,这是一个 UX 灾难,因为正在加载的图像在你阅读它的时候已经挂载到 DOM。

所以我更喜欢通过渲染 a 来坚持,<Spinner/>直到我的图像准备好。这就是为什么<BlogPost>是一个具有以下代码的类组件:

class BlogPost extends React.Component {
  constructor(props) {
    super(props);
    this.state={
      pending: true,
      imagesToLoad: 0,
      imagesLoaded: 0
    };
  }

  preloadImages(blogPostMedia) {
    this.setState({
      pending: true,
      imagesToLoad: 0,
      imagesLoaded: 0
    });

    ... some more code ...
    // Get images urls and create <img> elements to force browser download
    // Set pending to false, and imagesToLoad will be = imagedLoaded
  }

  UNSAFE_componentWillReceiveProps(nextProps) {
    if (this.props !== nextProps) {
      this.preloadImages(nextProps.singleBlogPost.media);
    }
  }

  componentDidMount() {
    this.preloadImages(this.props.singleBlogPost.media);
  }

  render() {
    return(
        this.state.pending ?
          <Spinner/>
        : (this.state.imagesLoaded < this.state.imagesToLoad) ?
            <Spinner/>
          : <BlogPostStyledDiv dangerouslySetInnerHTML={getParsedMarkdown(this.props.singleBlogPost.content)}/>
    );
  }
}

export default BlogPost;

起初我是在调用preloadImages()唯一的内部componentDidMount()方法。这对于我用它渲染的第一篇文章来说完美无缺。

但是只要我点击下一个帖子链接;由于我的<BlogPost>组件已经安装,componentDidMount()因此不会再次被调用,并且我将通过单击链接(这是一个单页应用程序)呈现的所有后续帖子都不会从该preloadImages()功能中受益。

所以我需要一种方法来重置和预加载在更新周期内state收到的新 blogPost 的图像,因为它已经安装了组件。props<BlogPost>

我决定preloadImages()从方法内部调用相同的函数UNSAFE_componentWillReceiveProps()。基本上它将我重置state为初始条件,因此 a<Spinner/>会立即显示,并且博客文章仅在所有图像已加载时才会呈现。

它按预期工作,但由于该方法的名称包含“不安全”一词,我很好奇是否有更好的方法来做到这一点。即使我认为我没有在其中做任何“不安全”的事情。我的组件仍然尊重它props,并且无论如何都不会改变它们。它刚刚被重置为其初始行为。

回顾:我需要一种将我已安装的组件重置为其初始值state并调用该preloadImages()方法(在更新周期内)的方法,以便它的行为与新安装的一样。有没有更好的方法或者我所做的一切都很好?谢谢。

标签: javascriptreactjs

解决方案


我会停止使用componentWillReceiveProps()资源)。如果您不想要不和谐的效果,可以避免它的一种方法是从<BlogPost/>的父级加载信息,并且只有在加载信息后,才能将其<BlogPost/>作为道具传递。

但无论如何,您可以使用keys 通过从头开始重新创建组件(资源)将组件重置回其原始状态。


推荐阅读