我的网站有一个ChatBox组件,它显示用户的聊天记录。聊天记录在我的 firestore 中没有排序,所以我想 (1( 在通过 Redux props (this.props.profile.chats_history( 获取数据后,在 componentDidMount 中从最晚到最不新鲜进行排序,并且 (2( 将字段"chatlist"设置为排序数组的状态。问题是接收 props 需要时间,当调用 array.sort(( 方法时,控制台报告数组未定义。我试图通过使用异步和等待关键字来绕过它,但我的解决方案不起作用。
我的解决方案
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
})
}
您可以做的是等待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
,这将触发组件更新。
每次更新this.props
或this.state
时都会触发componentDidUpdate
。您在代码中看到的参数prevProps
和prevState
是对触发componentDidUpdate
的更新发生之前this.props
和this.state
值的引用。
componentDidUpdate
将被多次触发,并且您希望仅在加载触发this.props.chats_history
时才执行sort
函数。为此,您将(与_.isEqual
(prevProps.chats_history
与this.props.chats_history
进行比较。它们是否不相等,这意味着this.props.chats_history
刚刚被修改(在本例中为已加载(,因此您仅在这些情况下调用sort
。
我使用lodash
库中_.isEqual
的原因是,如果我进行==
或===
比较,它将始终返回true
this.props.chats_history
因为它是一个数组,因此它将比较引用而不是数组的内容。如果使用_.isEqual
它会进行深入比较,并且仅当this.props.chats_history
的每个元素都等于prevProps.chats_history
的每个元素时才返回true
。
由于您随后调用了this.setState()
,因此将再次调用componentDidUpdate
,但if
块将返回false
并且不会再次运行sort
代码。
这有意义吗?
你可以改用getDerivedStateFromProps。
static getDerivedStateFromProps(props, state) {
const sortedChat = props.profile.chats_history?[...props.profile.chats_history].sort((a,b)=>{/*logic*/}):[]
return { sortedChat };
}
您可以通过比较状态中的当前数据和 props 中接收的数据来优化渲染。这再次取决于您的数据。就个人而言,我会在profile.chats中保留时间戳,并且仅在时间戳更改时才更新状态。此外,排序会更改原始数组顺序。所以,在你像我上面所做的那样排序之前克隆。