React中如何让Page组件获取自身在PagesContainer中的位置?
实现Page组件自动获取页码方案
要实现让Page组件自动感知自己在PagesContainer中的位置并获取页码,我们可以通过React Context + 父组件遍历子元素的方式来实现,完全不需要手动传递number props,调整Page的顺序时页码会自动更新。
具体实现步骤
1. 创建PageContext用于传递页码
首先创建一个Context,用来在PagesContainer和Page组件之间传递当前页码:
import { createContext, useContext } from 'react'; const PageContext = createContext(null);
2. 实现useGetCurrentPage Hook
封装一个自定义Hook,让Page组件可以直接获取当前页码:
export function useGetCurrentPage() { const pageNumber = useContext(PageContext); if (pageNumber === null) { throw new Error('useGetCurrentPage 必须在 PagesContainer 内部使用'); } return pageNumber; }
3. 改造PagesContainer组件
让PagesContainer遍历自己的直接子元素,给每个Page组件包裹Context.Provider并注入对应的页码(索引+1,因为页码从1开始):
import { Children, cloneElement } from 'react'; export function PagesContainer({ children }) { const indexedChildren = Children.map(children, (child, index) => { // 仅对Page组件进行处理,需要确保Page组件的displayName或name为'Page' if (child.type.displayName === 'Page' || child.type.name === 'Page') { return ( <PageContext.Provider value={index + 1}> {cloneElement(child)} </PageContext.Provider> ); } // 非Page组件直接原样返回 return child; }); return <div>{indexedChildren}</div>; }
4. Page组件中使用Hook
在Page组件中直接调用自定义Hook获取页码:
export function Page() { const currentPage = useGetCurrentPage(); return <div>第 {currentPage} 页</div>; } // 给Page组件设置displayName,确保类型判断准确(如果是默认导出的话尤其重要) Page.displayName = 'Page';
使用示例
不管是手动编写的Page还是循环生成的Page,调整顺序后页码都会自动更新:
手动编写的场景
<PagesContainer> <Page /> {/* 显示:第1页 */} <Page /> {/* 显示:第2页 */} <div>这是一个非Page元素,不受影响</div> <Page /> {/* 显示:第3页 */} </PagesContainer> // 调整顺序后 <PagesContainer> <Page /> {/* 第1页 */} <Page /> {/* 第2页 */} <Page /> {/* 第3页 */} </PagesContainer>
循环生成的场景
<PagesContainer> {Array.from({ length: 4 }).map((_, idx) => ( <Page key={idx} /> {/* 依次显示第1-4页,调整循环顺序页码自动变化 */} ))} </PagesContainer>
注意事项
- 确保Page组件是PagesContainer的直接子元素,如果Page被其他组件包裹,需要调整PagesContainer的遍历逻辑(比如递归遍历子元素)。
- 若Page组件是默认导出,记得设置
displayName,否则child.type.name会是'default',导致类型判断失效。 - 如果需要支持动态添加/删除Page组件,该方案同样适用,页码会自动重新计算。
内容的提问来源于stack exchange,提问作者Berry
相关产品推荐
相关产品推荐

