我的网站上有一个ChatBox组件,它显示用户的聊天记录。聊天记录在我的Firestore中没有排序,因此一旦我通过Redux道具(this.props.profile.chats_history)和(2)设置获取数据后,我想(1)将其在componentDidMount中从最新到最近排序聊天框状态中的“聊天列表”字段到已排序的数组。问题在于接收道具需要花费时间,并且在调用array.sort()方法时,控制台报告该数组未定义。我尝试使用async和await关键字解决此问题,但是我的解决方案无法正常工作。
我的解决方案
async componentDidMount() {
let chatlist;
await this.props.profile.chats_history;
chatlist = this.props.profile.chats_history.sort(function(a, b) {return a.time - b.time});
this.setState({
chatlist: chatlist
})
}
答案 0 :(得分:1)
您可以使用chats_history
而不是componentDidUpdate
等待componentDidMount
更新。在这里,我在this.props.chats_history
上做得很深。
const _ = require("lodash")
componentDidUpdate(prevProps, prevState) {
if (!_.isEqual(prevProps.profile.chats_history, this.props.profile.chats_history)) {
chatlist = this.props.profile.chats_history.sort(function(a, b) {return a.time - b.time});
this.setState({
chatlist: chatlist
})
}
}
基本上,这里发生的是,一旦安装了组件,this.props.chats_history
就会有一些值,但是还没有真正的值列表。在某个时候,this.props.chats_history
将被加载,这将触发组件更新。
componentDidUpdate
或this.props
时都会触发 this.state
。您在我的代码中看到的自变量prevProps
和prevState
是对触发this.props
的更新发生之前的this.state
和componentDidUpdate
值的引用。
componentDidUpdate
将被多次触发,并且仅当加载sort
时才执行this.props.chats_history
函数。为此,您将_.isEqual
与prevProps.chats_history
(与this.props.chats_history
进行比较。它们是否不相等相等,这意味着this.props.chats_history
刚刚被修改(在本例中为已加载),因此仅在这种情况下才调用sort
。
我从_.isEqual
库中使用lodash
的原因是,如果我进行了==
或===
比较,它将总是返回true
,因为{ {1}}是一个数组,因此它将比较引用而不是数组的内容。如果您使用this.props.chats_history
,则会进行深度比较,并且仅在_.isEqual
的每个元素等于true
的每个元素时才返回this.props.chats_history
。
由于您随后调用prevProps.chats_history
,因此将再次调用this.setState()
,但是componentDidUpdate
块将返回if
,并且不会再次运行false
代码。
这有意义吗?
答案 1 :(得分:0)
您可以改用getDerivedStateFromProps。
static getDerivedStateFromProps(props, state) {
const sortedChat = props.profile.chats_history?[...props.profile.chats_history].sort((a,b)=>{/*logic*/}):[]
return { sortedChat };
}
您可以通过比较状态中的当前数据和道具中的接收数据来优化渲染。这再次取决于您的数据。就个人而言,我将在profile.chats中保留一个时间戳,并仅在时间戳更改时更新状态。此外,排序会更改原始数组的顺序。因此,请在进行上述操作之前先进行克隆。