使用useEffect设置的上下文状态仅将上下文设置为触发的最后一个useEffect

时间:2019-11-21 23:26:28

标签: reactjs react-hooks

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

  • 上下文当前仅设置最后一个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的工作原理。从我的方式 用[]写的,我想这相当于 componentDidMount()。所以对我来说,它应该使用 组件安装完成后即可获取数据。
  2. 在上下文b / c中没有足够的时间更新状态,这可能是生命周期问题吗?

谢谢

1 个答案:

答案 0 :(得分:2)

上一次更新的原因是因为您没有使用状态更新程序的回调模式,状态更新程序是异步的,并且当多个更新同时运行时,不应该理所当然地返回当前状态。

>

当您尝试传播while (rowIt.hasNext()) { try { Thread t1 = new Thread() { public void run() { DimCompany comp = new DimCompany(); Row row = rowIt.next(); Cell c = row.getCell(cmpName); if (c != null && c.getCellType() != c.CELL_TYPE_BLANK) { if (cmpName != null && row.getCell(cmpName) != null) { comp.setCompanyName(row.getCell(cmpName).toString()); comp.setSourecLevel1("MCA"); } if (cmpUId != null && row.getCell(cmpUId) != null) { comp.setCompanyUniqueId(row.getCell(cmpUId).toString()); } if (compType != null && row.getCell(compType) != null) { comp.setCompType(row.getCell(compType).toString()); } if (foundedDate != null && row.getCell(foundedDate) != null) { comp.setFoundedDate(row.getCell(foundedDate).toString()); } //save record int i = parseDataDao.saveCompany(comp); } } }; t1.start(); } catch (Exception e) { System.out.println(e); } } 时,实际上是在效果内的每个sectionTops调用中传播了初始的空对象。

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

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

addSectionTop