我有一个<BlogPost>组件,它本来可以是无状态功能组件,但由于以下原因而成为类有状态组件:

它呈现的blogPost项(以props接收)具有嵌入到html标记内容中的图像,这些图像是我使用marked库进行解析的,并呈现为博客帖子,且其段落h1,h2,h3等之间。

事实是,在将帖子内容呈现给客户端之前,我需要预加载这些图像。我认为,如果您开始阅读一个段落,突然之间它下降了400px,这是一个UX灾难,因为正在加载的图像在阅读时已被装载到DOM上。

所以我更喜欢通过渲染<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并在更新周期内预加载作为props接收的新blogPost的图像,因为<BlogPost>组件已经安装。

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

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

回顾:我需要的是一种将已安装的组件重置为其初始state并调用preloadImages()方法(在更新周期内)的一种方法,这样它就可以像刚安装时一样工作。有没有更好的方法,或者我做的还好吗?谢谢。

最佳答案

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

但是无论如何,您可以使用key通过从头重新创建组件(resource)将组件重置为其原始状态。

10-05 20:51
查看更多