【问题标题】:useState doesn't update the value, and the value keep remains nulluseState 不更新值,值 keep 保持为空
【发布时间】:2020-02-16 13:55:32
【问题描述】:

我正在使用 React 构建我的网站,并且我正在使用 useState 来获取悬停项目的 id。

但是当我使用 setState 获取值时,它不会更新并保持为“空”

所以在控制台上,我可以看到 event.target.id 被识别,但即使在 setState 事件之后,状态值也返回 null。

谁能提供一些关于这里发生了什么的线索?

这是代码

import React from 'react'
import { BrowserRouter as Router, Route, Link } from 'react-router-dom'
import styled from 'styled-components'



const WorksTitle = props => {
  const { type, title, imgSrc, link, year } = props
  const [currentMenu, setCurrentMenu] = React.useState(null)

  const handleHover = event => {
    console.log(
      'event target: ',
      event.target,
      ' / ',
      'event target id: ',
      event.target.id
    )
    **console.log(event.target.id)
    setCurrentMenu(event.target.id)
    console.log(currentMenu)**
  }

  const handleMouseOut = event => {
    console.log('mouse out from:', event.target.id)
    setCurrentMenu(null)
  }

  return (
    <StyledWorksTitle>
      <TitleItem id={title} onMouseOverCapture={handleHover} onMouseOut={handleMouseOut}>
        <div className={`itemWrapper ${(currentMenu === { title } ||
            currentMenu === null) && 'activated'}`}
          id={title}>
          <Link to={link}></Link>
        </div>
      </TitleItem>
    </StyledWorksTitle>
  )
}

/* styled-components */

export default WorksTitle

【问题讨论】:

标签: javascript reactjs


【解决方案1】:

setState 是一个异步调用,这意味着 console.log 在它不会有更新的值之后立即。出于调试目的,请执行以下操作: 在 StyledWorksTitle 之后创建一个按钮并在其中写入如下:

   <button onClick={()=>console.log(currentMenu)}></button>

您现在应该可以看到更新后的值了。

至于如何处理它的实现。我建议使用 useEffect() 并将 currentMenu 状态作为其依赖项传递。

   useEffect(()=>{
    //write a function to push hovered item id into an array or something
   },currentMenu)

这是非常通用的,因为我不知道你想用这个 ID 做什么,但无论如何这会帮助你。

【讨论】:

  • 即使状态更新函数异步运行也不能解释这种情况下代码的行为。调用 setCurrentMenu 后仍然得到状态的旧值的原因是 closure。所以你的答案的推理是不正确的。您可能想更新您对这一事实的回答
【解决方案2】:

useState 是异步的,因此 currentMenu 直到下一次渲染才会更新。

Here 是一个用于演示的沙盒示例。

【讨论】:

  • 即使更新函数是异步的,也无法解释上述代码中的行为。这是因为 closure。在反应中,道具和状态是不可变的,每个渲染都有自己的道具、状态和事件处理程序。所以在这种情况下,你仍然会得到旧的状态值,因为它是你的事件处理程序 *closes 超过
  • 我明白你的意思,但是,这在技术上并不完全正确。您可以通过直接分配给状态来绕过它。这将在console.log 下直接更新,显示它发生了变异状态。我知道这违背了一切反应,但只是一个例子。 here
猜你喜欢
  • 2021-10-09
  • 2020-12-22
  • 2023-01-27
  • 2020-10-28
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-11-15
  • 2020-07-19
相关资源
最近更新 更多