我有一个<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()
不会再被调用,并且我将通过单击链接(这是一个单页应用程序)来呈现的所有后续帖子都不会从{ {1}}功能。
所以我需要一种方法来重置preloadImages()
并预加载在更新周期内以state
接收的新blogPost的图像,因为已经安装了props
组件。>
我决定从<BlogPost>
方法内部调用相同的preloadImages()
函数。基本上是将我的UNSAFE_componentWillReceiveProps()
重置为初始状态,因此state
会立即显示,并且该博客文章仅在所有图像都加载后才会呈现。
它可以按预期工作,但是由于该方法的名称包含单词“ UNSAFE”,我很好奇是否有更好的方法可以做到这一点。即使我认为我没有在其中执行任何“不安全”的操作。我的组件仍然尊重其<Spinner/>
,并且无论如何都不会更改它们。它只是被重置为其初始行为。
RECAP:我需要的是一种将已安装的组件重置为其初始props
并调用state
方法(在更新周期内)的一种方法,这样它就可以像刚安装时一样工作。有没有更好的方法,或者我做的还好吗?谢谢。
答案 0 :(得分:1)
componentWillReceiveProps
已过时,根据情况应替换为getDerivedStateFromProps
或componentDidUpdate
。
由于preloadImages
是异步副作用,因此应同时在componentDidMount
和componentDidUpdate
中调用它:
componentDidMount() {
this.preloadImages(this.props.singleBlogPost.media);
}
componentDidUpdate() {
this.preloadImages(this.props.singleBlogPost.media);
}
答案 1 :(得分:1)