【问题标题】:How to replace useEffect with componentDidMount if we call a callback function inside componentDidMount?如果我们在componentDidMount内部调用回调函数,如何用componentDidMount替换useEffect?
【发布时间】:2020-02-12 16:09:02
【问题描述】:

通过使用useEffect,我的数组状态变量没有附加上一个值,但componentDidMount做了

我在使用useEffect时console.log out消息,并且所有消息都被正确打印出来,但是状态没有被存储,如果我将messages状态变量设置为useEffect的依赖项,它会进入一个无限循环

// with useEffect hook
function App() {
  const [messages, setMessages] = useState([]);

  useEffect(() => {
    const chatManager = new ChatManager({
      instanceLocator: instanceLocator,
      userId: 'Henry',
      tokenProvider: new TokenProvider({
        url: tokenUrl
      })
    });

    chatManager.connect()
      .then(currentUser => {
        currentUser.subscribeToRoomMultipart({
          roomId: '7b7a1d23-e869-4c19-8eab-e88d5144dd72',
          hooks: {
            onMessage: message => {
             console.log([...messages]);
              setMessages([...messages, message]);
            }
          }
        })
      }).catch(err => {
        console.log('Error on connection', err)
      })
  }, [])

  return (
    <div className="app">
      <RoomList />
      <MessageList messages={messages}/>
      <SendMessageForm />
      <NewRoomForm />
    </div>
  );
}

export default App;

// with componentDidMount
class App extends React.Component {

  constructor() {
    super()
    this.state = {
      messages: []
    }
  }

  componentDidMount() {
    const chatManager = new ChatManager({
      instanceLocator,
      userId: 'Henry',
      tokenProvider: new TokenProvider({
        url: tokenUrl
      })
    })

    chatManager.connect()
      .then(currentUser => {
        currentUser.subscribeToRoomMultipart({
          roomId: '7b7a1d23-e869-4c19-8eab-e88d5144dd72',
          hooks: {
            onMessage: message => {
              this.setState({
                messages: [...this.state.messages, message]
              })
            }
          }
        })
      })
  }

  render() {
    return (
      <div className="app">
        <RoomList />
        <MessageList messages={this.state.messages} />
        <SendMessageForm />
        <NewRoomForm />
      </div>
    );
  }
}

export default App

我希望使用 useEffect 的结果与 componentDidMount 相同,它将消息状态数组变量中的所有消息散列,但是通过使用 useEffect,我可以控制所有消息,但是消息状态数组变量是空的,所以最终结果只是最新消息。

【问题讨论】:

  • 看起来您的组件在渲染之间正在重置状态。

标签: reactjs react-lifecycle react-lifecycle-hooks


【解决方案1】:

由于你的状态依赖于当前的状态值,你需要使用setMessages的函数形式。这意味着您不需要包含 messages 作为依赖项(因为它实际上不是依赖项):

  useEffect(() => {
    ...

    chatManager.connect()
      .then(currentUser => {
        currentUser.subscribeToRoomMultipart({
          roomId: '7b7a1d23-e869-4c19-8eab-e88d5144dd72',
          hooks: {
            onMessage: message => {
              setMessages(prevMessages => [...prevMessages, message]);
            }
          }
        })
      })
  }, [])

查看 React 文档了解更多信息: https://reactjs.org/docs/hooks-reference.html#functional-updates

【讨论】:

    猜你喜欢
    • 2021-01-26
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2023-04-06
    • 1970-01-01
    • 2017-10-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多