我想把它转换成一个useEffect钩子:
码
componentDidMount () {
this.messagesRef.on('child_added', snapshot => {
const message = snapshot.val();
message.key = snapshot.key;
this.setState({messages: this.state.messages.concat(message
)});
});更新代码
const MessageList = () => {
const [messages, setMessage] = useState([]);
const [usernames, setUsernames] = useState('');
const [contents, setContents] = useState('');
const [roomId, setRoomId] = useState('');
const messagesRef = MessageList.props.firebase.database().ref('messages');
useEffect(() => {
messagesRef.on('child added', snapshot => {
const message = snapshot.val();
message.key = snapshot.key;
const [messages, setMessages] = useState({messages: messages.concat(message)});
});
})
}现在它给了我一个useState cannot be used in a callback。
我如何正确地解决这个问题或转换这个问题?
发布于 2019-05-22 04:19:10
那里有几件事。首先,要修复代码,可以将useEffect更新为:
useEffect(() => {
messagesRef.on('child added', snapshot => {
const message = snapshot.val();
message.key = snapshot.key;
setMessages(messages.concat(message)); // See Note 1
}, []); // See Note 2注1
setMessages行是如何更新状态的。从某种意义上说,useState与“旧”setState略有不同,它将完全取代状态值。React 文档说:
这是因为当我们更新一个状态变量时,我们会替换它的值。这与类中的this.setState不同,该类将更新的字段合并到对象中。
注2
React改变了我们构建应用程序的方式,这并不是对旧生命周期的真正“翻译”。
最后一行中的空括号([])将使您的代码“类似”componentDidMount,但最重要的是,只运行一次效果。
Dan Abramov说(删除了一些原始文本):
虽然可以使用useEffect(fn,[]),但它并不是完全等价的。与componentDidMount不同,它将捕获道具和状态。因此,即使在回调中,您也会看到最初的道具和状态。(...)请记住,效果的心理模型与componentDidMount和其他生命周期不同,试图找到它们的确切对应物可能会使您感到困惑而不是帮助。为了提高效率,您需要“考虑效果”,并且他们的心智模型更接近于实现同步,而不是响应生命周期事件。
关于useEffect 这里的完整文章。
发布于 2019-05-22 04:16:10
您试图再次声明状态,而不是使用状态更新程序。
useEffect(() => {
messagesRef.on('child added', snapshot => {
const message = snapshot.val();
message.key = snapshot.key;
// setMessages is the state updater for messages
// instead of an object with messages: messagesArray
// just save it as an array the name is already messages
setMessages([...messages, message]);
});
// useEffect takes an array as second argument with the dependencies
// of the effect, if one of the dependencies changes the effect will rerun
// provide an empty array if you want to run this effect only on mount
}, []);发布于 2021-04-12 12:16:34
我找到了一种不需要修改html的替代解决方案。我们创建一个高阶组件,该组件显示一些等待元素,并在componentDidMount中切换状态或使用effect来呈现目标组件。
import React, { useEffect, useState } from 'react';const Loading = (props) => {
const [loading, setLoading] = useState(true);
useEffect(() => {
setLoading(false);
}, []);
return (
<>
{loading ?
<div style={{
display: 'flex',
justifyContent: 'center',
alignItems: 'center',
width: '100%',
height: '100%',
fontSize: '5vh'
}}>
Loading...
</div> :
props.children}
</>
);
};
export default Loading;缺点是动画元素不起作用。
https://stackoverflow.com/questions/56249151
复制相似问题