首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >React useEffect钩子- componentDidMount to useEffect

React useEffect钩子- componentDidMount to useEffect
EN

Stack Overflow用户
提问于 2019-05-22 04:05:17
回答 3查看 37.6K关注 0票数 9

我想把它转换成一个useEffect钩子:

代码语言:javascript
复制
componentDidMount () {
   this.messagesRef.on('child_added', snapshot => {
    const message = snapshot.val();
    message.key = snapshot.key;
    this.setState({messages: this.state.messages.concat(message 
  )});
});

更新代码

代码语言:javascript
复制
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

我如何正确地解决这个问题或转换这个问题?

EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2019-05-22 04:19:10

那里有几件事。首先,要修复代码,可以将useEffect更新为:

代码语言:javascript
复制
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 这里的完整文章。

票数 14
EN

Stack Overflow用户

发布于 2019-05-22 04:16:10

您试图再次声明状态,而不是使用状态更新程序。

代码语言:javascript
复制
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
}, []);
票数 1
EN

Stack Overflow用户

发布于 2021-04-12 12:16:34

我找到了一种不需要修改html的替代解决方案。我们创建一个高阶组件,该组件显示一些等待元素,并在componentDidMount中切换状态或使用effect来呈现目标组件。

代码语言:javascript
复制
import React, { useEffect, useState } from 'react';
代码语言:javascript
复制
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;

缺点是动画元素不起作用。

票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/56249151

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档