基于 url 的页面更新的 React useLocation 钩子的替代方案?

Alternative to React useLocation hook for page update based on url?

这是一个棘手的问题。

一些信息:
我可以有多个 collection 多张图片和每个 header 的特定徽标 collection。
我的collectionurl看起来像这样/collection/{collectionId}/item/{itemId}

const MyApp = () => {
    // unrelated code
    return(
        <BrowserRouter>
            <SiteLayout>
        </BrowserRouter>
    )
}

const SiteLayout = () => {
    location = useLocation()
    collectionId = location.pathname.split('/')[2] //gives me the collection Alias

    const [collData, setCollData] = useState()

    useEffect(() => {
        const getCollectionData = async() => {
            //fetch collection data
            //setCollData(fetched data)
        }
        getCollectionData()
    }, [collectionId])

    return(
        <CollectionContext.Provider value={collData}>
            <div className='mainContainer'>
                <div className='headerContainer'>
                    <Header/>
                </div>
                <div className='mainContent'>
                    <Route exact path='/collection/:collectionId' component={CollectionViewPage}>
                    <Route exact path='/collection/:collectionId/item/:itemId' component={ItemViewPage}
                </div>
                <div className='footerContainer'>
                    <Footer/>
                </div>
            </div>
        </CollectionContext.Provider>
    )

}
export default SiteLayout

我的想法:

我的问题:

我在寻找什么:如何重构它以在 collectionId 更改时更新,而不是每次 location 更改时更新?我需要这个是因为(很多事情,但为了简单起见)我希望 header 在我更改 collections 时更新,以便它可以使用正确的徽标,但我想阻止 <Header> 来自 re-rendering 如果我在 内导航 collection.

我试过的其他方法:
我试过删除 useLocation 并使用 window.location.pathname 但没有任何更新.

已解决


使用@HMR 的建议来回答原始问题:

If Header and CollectionViewPage are functional components maybe you can wrap [them] in React.memo If they still re render [...] look at what you need and maybe create a container that only picks what you actually need...


实施:

通过添加一个中间层,我可以拆分 location,然后根据我想要的任何部分记忆 SiteLayout

const MyApp = () => {
    // unrelated code
    return(
        <BrowserRouter>
            <LocationPartition>
        </BrowserRouter>
    )
}
export default MyApp

LocationPartition 中的位置(可能使用更好的名称):

const LocationPartition = () => {
    const location = useLocation()
    const collectionId = location.pathname.split('/')[2]
    return(
        <SiteLayout collection={collectionId}/>
    )
}
export default LocationPartition

所以在 SiteLayout 中,我现在可以根据从 LocationPartition

传递的 collection 道具进行记忆
const SiteLayout = memo(({collection})) => {

    const [collData, setCollData] = useState()

    useEffect(() => {
        const getCollectionData = async() => {
            //fetch collection data
            //setCollData(fetched data)
        }
        getCollectionData()
    }, [collection])

    return(
        <CollectionContext.Provider value={collData}>
            <div className='mainContainer'>
                <div className='headerContainer'>
                    <Header/>
                </div>
                <div className='mainContent'>
                    <Route exact path='/collection/:collectionId' component={CollectionViewPage}>
                    <Route exact path='/collection/:collectionId/item/:itemId' component={ItemViewPage}
                </div>
                <div className='footerContainer'>
                    <Footer/>
                </div>
            </div>
        </CollectionContext.Provider>
    )

}
export default SiteLayout


瞧瞧 ... React Profiler 现在只在我想要的地方显示重新渲染!