【问题标题】:React state updating in the dom but not in function在 dom 中反应状态更新但不在功能中
【发布时间】:2022-12-10 22:43:39
【问题描述】:

我在名为 handleLinkChange 的输入字段上有一个 onClick 事件,该事件验证其内容(YouTube 链接),如果它有效,则调用提取其 YouTube id 的函数。

在 onClick 事件中,我更新了链接状态,以便用户查看链接是否有效以及是否正在进行 ID 提取(由输入字段中的加载轮指示)。此时,状态会根据需要在 DOM 中更新。但是,当我在设置状态后到达getIdsFromLink函数时,链接状态仍然是初始值。这使得无法更改链接,例如,在解析 id 后用复选标记替换链接的加载指示器。

  // Links state
  const [links, setLinks] = useState([{ link: '', state: IS_VALID, errorMessage: '' }])

  // onChange event handler
  const handleLinkChange = (event, index) => {
    const clonedLinks = [...links]

    let value = decodeURI(event.target.value.trim())

    const { passesRegex, validityMessage } = checkLinkValidity(value)

    clonedLinks[index] = {
      link: value,
      state: passesRegex ? IS_VALIDATING_SERVER_SIDE : IS_ERROR,
      errorMessage: validityMessage,
    }

    setLinks(clonedLinks)

    if (clonedLinks[index] !== '' && passesRegex) {
      getIdsFromLink(clonedLinks[index].link, index)
    }
  }

  // Parser
  const getIdsFromLink = (link, index) => {
    console.log('links state', links) // initial state

    socket.emit('getIds', link)

    socket.on('idsParsed', newIds => {
      console.log('links state after parse', links) // initial state
    })
  }

  // Shortened return
  return (
      links.map((link, index) => (
        <Input
          value={link.link} 
          onChange={event => handleLinkChange(event, index)}
        />

      {link.link && (
        <FontAwesomeIcon
          icon={link.state === IS_VALID ? faCheck : link.state === IS_ERROR ? faTimes : faSpinner}
        />
      )}
    )
  ))

我知道状态是异步的,我也尝试用 useEffect 观察状态变化,但我无法以这种方式重构我的代码,而且我有另一个严重依赖于链接状态的状态对象,所以我放弃了那个.

即使当我尝试使用 flushSync 同步更新状态时,我也有同样的效果。

非常感谢您的帮助!谢谢!

【问题讨论】:

  • clonedLinks 代表您当前的状态,因此您可以将其传递给getIdsFromLink()。如果您计划使用getIdsFromLink 中的第二个setLinks() 调用来更新您的状态,那么您应该删除第一个setLinks() 调用,因为它会被您所做的第二个setLinks() 调用覆盖。您还可以使用setLinks(currLinks =&gt; ...)访问当前状态值
  • @NickParsons 我不将clonedLinks 传递给getIdsFromLink() 的原因是在解析id(这是一个套接字调用)期间,用户可以添加更多链接,因此,当链接解析完成时,它的clonedLinks可能无法反映链接状态的最新变化。此外,在解析之前我需要setLinks(),以便用户看到输入旁边的加载指示器。
  • @NickParsons 实际上使用带有函数参数的setLinks 可以访问当前状态,所以我在上面评论中描述的问题已经解决了!所以现在我在函数参数中更改我的 links 对象并在最后返回新对象。我只需要确保克隆函数参数的当前状态对象以强制重新呈现状态。

标签: javascript reactjs react-hooks


【解决方案1】:

感谢 cmets 中的 Nick,我将回答我的问题。

基本上我保持 handleLinkChange 功能不变。但是在 getIdsFromLink 函数中,当从服务器解析链接时 - 这是我必须更新状态的地方 - 我使用 setLinks 并将函数作为参数。该函数接收一个类似于当前状态的参数。我所要做的就是制作对象的副本(以便重新渲染工作),然后对其进行更改并最终返回新对象。

  const getIdsFromLink = (link, index) => {
    socket.emit('getIds', link)

    socket.once('idsParsed', ids => {
      // Function parameter to get current state
      setLinks(_currentLinks => {
        const currentLinks = [..._currentLinks] // copy to force rerender

        currentLinks[index].state = IS_VALID
        currentLinks[index].ids = ids
        
        console.log('finished currentLinks', currentLinks) // newest state

        return currentLinks
      })
    })
  }

【讨论】:

    猜你喜欢
    • 2022-01-21
    • 2018-09-27
    • 1970-01-01
    • 2023-02-13
    • 1970-01-01
    • 2020-04-21
    • 1970-01-01
    • 2022-07-01
    • 2022-06-27
    相关资源
    最近更新 更多