我有一个<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)将组件重置为其原始状态。