[英]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,這是什么奇怪的行為?
我正在談論的參考是cartContainer和pageShdowCover我發現當我停止我的 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 時,父級不會重新渲染,因此組件A
, B
, C
不會重新渲染,因此他們不知道新分配的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 上的這個答案中找到了解決方案。 我來這個問題是因為A
、 B
和C
正在使用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.