簡體   English   中英

當我使用 useContext 掛鈎時,為什么包裹在 forwardRef 中的功能組件會收到 null 引用?

[英]Why do functional components wrapped in forwardRef receive null refs when I use the useContext hook?

我有一個sidebarCart組件,它基本上是一個購物車組件,它被包裹在forwardRef鈎子中,並包含useImperativeHandle以將 function 傳遞給父級 App。 在我引入useContext鈎子之前一切正常,現在sidebarCart內的 refs 變為 null,這是什么奇怪的行為?

我正在談論的參考是cartContainerpageShdowCover我發現當我停止我的 nodejs 服務器時,這個問題就消失了。

這是sidebarCart組件。

import React ,{createRef,forwardRef,useImperativeHandle,useContext,useEffect}from 'react'
import CartItem from './CartItem'
import {MyContext} from '../../Context/ProductsProvider'


const SideBarCart=forwardRef((props,ref)=>{
    const {setCart,cart} =useContext(MyContext)
    const cartContainer  = createRef()
    const pageShdowCover = createRef()

    const slideOut=e=>{
        cartContainer.current.style.right='-400px'
        pageShdowCover.current.style.opacity='0'
        setTimeout(()=>pageShdowCover.current.style.display='none', 600);
    }
    useImperativeHandle(ref, () => ({
        slideIn(){
           pageShdowCover.current.style.display='block'
           cartContainer.current.style.right='0'
           pageShdowCover.current.style.opacity='1'
        }
    }),[pageShdowCover,cartContainer]);
 
    return (
        <div>
            <div className="pageShdowCover"  ref={pageShdowCover}  ></div>
            <div className="SideContainer cart" ref={cartContainer}>
                <div className="cart__top">
                    <h1>Cart</h1>
                   <i className="far fa-times-circle Close" onClick={slideOut}></i>  
                   <a onClick={slideOut}>x</a>
                </div>
                <div className="cart__body">  
                </div>
        </div>
        </div>
    )
})

export default SideBarCart

我認為useContext鈎子會導致子級重新渲染而沒有父級重新渲染。 Refs 在更改時不會觸發重新渲染,因此從父級傳遞給子級的 refs 可能是陳舊的? (我認為這就是答案——我可能不正確)。

總之(對我有用):要解決我遇到的問題,只需在 state 中存儲一個 ref 以在 ref 更改時觸發重新渲染

===

解釋

我的用例是我有一個有 4 個孩子的父組件。 其中一個孩子是 header,我希望兄弟姐妹能夠在使用ReactDOM.createPortal呈現控件時“注入”控件

- Parent
 - Header
 - A
 - B
 - C  

我發現如果我只使用一個 ref,當 ref 分配給 DOM 時,父級不會重新渲染,因此組件ABC不會重新渲染,因此他們不知道新分配的ref.current值。

IE 以下不起作用

const Parent = () => {
  const ref = useRef()

  return (
   <div>
    <Header ref={el => { ref.current = el } />
    <C ref={ref} />
    <B ref={ref} />
    <C ref={ref} />
   </div>
  )
}

// A, B, C have the same signature
const A = forwardRef((props, ref) => {
  return (
    <div>
      {createPortal(<SomeComponent />, ref.current)}
      <OtherComponent />
    </div>
  )
})

我在 StackOverflow 上的這個答案中找到了解決方案。 我來這個問題是因為ABC正在使用useContext(...) 以前對我來說,當 state 是在Parent中創建而不是使用上下文時,上面的代碼是有效的 - 可能是因為父級正在重新渲染並留下陳舊的 refs 或其他東西(我認為它是“意外地”工作的)。 即問題與上下文無關,而是如何觸發重新渲染。

此代碼確實有效

const Parent = () => {
  const [ref, setRef] = useState()

  return (
   <div>
    <Header ref={el => { setRef(el) } />
    <C ref={ref} />
    <B ref={ref} />
    <C ref={ref} />
   </div>
  )
}

// A, B, C have the same signature
const A = forwardRef((props, ref) => {
  return (
    <div>
      {createPortal(<SomeComponent />, ref)}
      <OtherComponent />
    </div>
  )
})

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM