React useLocation钩子的替代方法,用于基于URL的页面更新?

这是一个棘手的问题。

一些信息
我可以有多个图像的多个集合,并且每个集合都有一个特定的标题徽标。
我的收藏网址看起来像这样/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

我的想法:

  • 我以这种方式进行设置,因为我无法在useLocation()之外使用<BrowserRouter>,并且想要更新我的collectionContext(其中包含有关我所在集合的信息,包括特定集合的信息)标头徽标)(collectionId更改时,location

我的问题:

  • 当我从一个项目移到另一个项目时,内部,例如,标头和其他所有内容仍会重新呈现

    来自-/collection/ 收藏1 / item / 1
    到-/collection/ 收藏1 / item / 2

  • 我的想法:该标头不应更新,因为collectionId从未更改。 但是,当我在React开发工具中查看事件探查器时,它说Header发生了变化,因为父项发生了变化,紧随其后的是<Route>,这是因为其状态(location )更改。

我要寻找的内容:如何在collectionId更改时(而不是每次location更改时)重构它以进行更新?我需要这样做是因为(很多事情,但是为了简单起见)我希望在更改集合时更新标题,以便可以使用正确的徽标,但是如果我想防止<Header>重新呈现,正在范围内浏览。

我尝试过的其他事情
我尝试过删除useLocation并改为使用window.location.pathname,但没有任何更新。

lawdragon 回答:React useLocation钩子的替代方法,用于基于URL的页面更新?

已解决


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

  

如果Header和CollectionViewPage是功能组件,也许您可​​以将它们包装在React.memo中。如果它们仍然重新呈现,请查看您的需求,也许创建一个只选择您实际需要的容器。


实施:

通过添加中间层,我可以拆分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中,我现在可以根据从collection传来的LocationPartition道具来进行记忆。

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现在只显示重新渲染我想要的位置!

本文链接:https://www.f2er.com/3164551.html

大家都在问