无法访问函数内部的状态变量

时间:2020-09-17 19:56:12

标签: javascript reactjs

我正在构建消息传递应用程序。我每隔5秒钟使用setTimeout从后端检索一次消息日志,并将其存储在状态变量中。每次超时时,我还将其滚动到聊天窗口的底部,但我试图使其仅在响应对象中有新消息时才发生。问题是我无法在检索它的函数中访问状态变量。理想情况下,我将响应对象的长度与状态变量的当前长度进行比较,以确定是否有新的响应。

这是我的代码:


  import React from "react"
  import axios from "axios"

  export default function Messaging(props) {

    const [messages, setMessages] = React.useState([])

    const getMessages = () => {

      const config = {
        method: "get",
        url: "localhost:3001/get-messages",
      }

      axios(config)
        .then((response) => {

         console.log(messages.length) // prints 0 in reference to the initial state value

          if (response.data.get.records.length !== messages.length) {
            // function to scroll to the bottom of the chat window
          }

          setMessages(response.data.get.records)
          setTimeout(getMessages, 5000)
          
     
        })
    }

    console.log(messages.length) // prints actual value correctly

    // Initial retrieval of chat log
    React.useEffect(() => {
      getMessages()
    }, [])
  }

在处理逻辑方面,我也乐于接受更好的建议。预先感谢!

1 个答案:

答案 0 :(得分:3)

setMessages将在下一个渲染器中更新messages

考虑到这一点,您可以创建一个效果,只要messages.length发生更改,它就会滚动到您的元素

  import React from "react"
  import axios from "axios"

  export default function Messaging(props) {

    const [messages, setMessages] = React.useState([])

    React.useEffect(() => {
      // store the id to clear it out if required
      let timeoutId

      const getMessages = () => {
        const config = {
          method: "get",
          url: "localhost:3001/get-messages",
        }
      
        axios(config)
          .then((response) => {
            // store the messages
            setMessages(response.data.get.records)
            // here we tell to poll every 5 seconds
            timeoutId = setTimeout(getMessages, 5000)
          })
      }

      getMessages()
      
      return () => {
        if (timeoutId) {
          clearTimeout(timeoutId)
        }
      }
    }, [setMessages])
    
    React.useEffect(() => {
      // code here to scroll
      // this would only trigger if the length of messages changes
    }, [messages.length])
  }

我还在您的第一个效果中添加了清理功能,因此当您卸载组件时,请清理timeout并避免任何额外的请求