【问题标题】:Context state being set with useEffect only setting the context to the last useEffect fired使用 useEffect 设置的上下文状态仅将上下文设置为最后一次触发的 useEffect
【发布时间】:2019-11-21 23:26:28
【问题描述】:

我正在尝试通过将 refName.current.offsetTop 值保存到来自多个组件的上下文中来制作平滑的滚动条。

  • Context 当前只设置了最后一个 setState。
  • 我的代码如下所示,以避免添加我运行的 2 个组件 useEffect 中的多个 setSectionTops(设置上下文状态)。

组件

const ProjectsList = () => {
  const {addSectionTop} = useContext(NavContext)
  let projectsRef = useRef()
  let ref2 = useRef()
  let ref3 = useRef()

  useEffect(()=>{
   addSectionTop('projects', projectsRef.current.offsetTop)
    addSectionTop('ref2', ref2.current.offsetTop)
    addSectionTop('ref3', ref3.current.offsetTop)
 
  },[])

  return (
    <section className="ProjectsList" id="ProjectsList" ref={projectsRef}>
      {/* {console.log('ProjectList:', navRefs)} */}
      <h2 ref={ref2}>Projects</h2>
      <div ref={ref3}>
        <Project />
      </div>
    </section>
  )
}

上下文

export const NavContext = createContext()

const NavContextProvider = props => {
  const [expanded, setExpanded] = useState(false)
  const [sectionTops, setSectionTops] = useState({})

  const toggleExpanded = () => {
    setExpanded(!expanded)
  }
  const addSectionTop = (newNavStr, refOffsetTop) => {
    // console.log('sectionTops:',sectionTops)
    const newSectionTop = {[newNavStr]: refOffsetTop}
    // console.log('newNavRef:',newNavRef)
    setSectionTops({...sectionTops, ...newSectionTop})
    console.log(sectionTops)
  }

  const scrollTo = refKey => {
    const refOffSetTop = sectionTops[refKey]
    window.scrollTo({ top: refOffSetTop, behavior: 'smooth' })
  }

  const value = {
    expanded,
    toggleExpanded,
    sectionTops,
    addSectionTop,
    scrollTo
  }

  console.log(value)

  return (
    <NavContext.Provider value={value}>{props.children}</NavContext.Provider>
  )
}

在这段代码的最后,sectionTops: 中的所有 I 都是 {ref3: 799}。

  1. 也许我不明白 useEffect 是如何工作的。从我如何拥有它 用 ,[] 写我在想它相当于 组件DidMount()。所以对我来说,它应该加载上下文 组件安装后的数据。
  2. 这可能是上下文中的生命周期问题 b/c 没有足够的时间来更新状态?

谢谢

【问题讨论】:

    标签: reactjs react-hooks


    【解决方案1】:

    你得到最后一次更新的原因是因为你没有使用状态更新器的回调模式,状态更新器是异步的,当多个更新一起运行时不应该想当然地返回当前状态。

    当您尝试传播 sectionTops 时,实际上是在效果内的每个 addSectionTop 调用中传播初始空对象。

    当您的状态依赖于最后一个状态或进行多个状态更新时,建议始终使用回调模式。

    您需要做的就是更改addSectionTop 中的状态更新器以使用这样的回调模式

    const addSectionTop = (newNavStr, refOffsetTop) => {
      setSectionTops(prevState => ({
        ...prevState,
        [newNavStr]: refOffsetTop,
      }))
    }
    

    【讨论】:

    • 谢谢,这很有效,让我阅读了更多关于 setState 的内容。我仍然很难理解 prevState 的来源。它在 setState 里面吗? b/c 它在渲染状态之前对状态进行批处理,以防止多次渲染。
    • @Krill React 将调用回调函数,将当前状态作为参数传递
    猜你喜欢
    • 2021-06-18
    • 1970-01-01
    • 1970-01-01
    • 2021-03-26
    • 2020-09-11
    • 1970-01-01
    • 2020-08-26
    • 2021-08-30
    • 1970-01-01
    相关资源
    最近更新 更多