React Admin:Show页面中useRecordContext()返回undefined问题
问题原因
你遇到的核心问题是钩子调用的时机和上下文范围不对。useRecordContext、useShowContext这些钩子需要在由<Show>或useShowController创建的上下文内部才能获取到数据,但你现在是在CardShow组件的顶层直接调用它们——此时<Show>组件还没完成渲染,上下文还没被注入,自然拿不到值。而<TextField>能正常显示,是因为它被包裹在<Show>/<SimpleShowLayout>内部,处于正确的上下文里。
解决方法
下面给两种可行的修复方案:
方案一:把钩子逻辑移到子组件中
把需要使用useRecordContext等钩子的代码放到一个子组件里,让子组件处于<Show>的上下文范围内:
// ./cards/CardShow.tsx import { useParams } from 'react-router-dom'; import { useRecordContext, useShowContext } from 'react-admin'; import { Show, SimpleShowLayout, TextField } from 'react-admin'; // 子组件:处于Show的上下文内 const CardShowContent = () => { const record = useRecordContext(); console.log(record); // 现在能拿到正确数据了 const { isLoading, record: record2 } = useShowContext(); console.log(record2); // 正常返回数据 return ( <SimpleShowLayout> <TextField source="id" /> <TextField source="title" /> </SimpleShowLayout> ) }; const CardShow = () => { const { id } = useParams(); console.log(id); // 正常显示id return ( <Show> <CardShowContent /> </Show> ) }; export default CardShow;
方案二:手动使用useShowController并提供上下文
如果想在顶层组件里直接获取数据,可以自己调用useShowController,然后用RecordContext.Provider把数据传递给子组件,注意此时要把<Show>换成<ShowView>(避免重复创建控制器):
// ./cards/CardShow.tsx import { useParams } from 'react-router-dom'; import { useRecordContext, useShowController, RecordContext, ShowView, SimpleShowLayout, TextField } from 'react-admin'; const CardShow = () => { const { id } = useParams(); console.log(id); // 正常显示id // 手动调用控制器,获取数据 const { data, isLoading } = useShowController({ recordId: id }); console.log(data); // 现在能拿到数据了 if (isLoading) return <div>Loading...</div>; return ( <RecordContext.Provider value={data}> <ShowView> <SimpleShowLayout> <TextField source="id" /> <TextField source="title" /> </SimpleShowLayout> </ShowView> </RecordContext.Provider> ) }; export default CardShow;
关键说明
<Show>组件内部已经封装了useShowController和上下文注入逻辑,所以它的子组件才能访问到记录数据。- 所有依赖React Admin上下文的钩子,都必须在对应的Provider(由
<Show>、<List>、<Edit>等组件或useXXXController钩子创建)的范围内调用。
内容的提问来源于stack exchange,提问作者benoit
相关产品推荐
相关产品推荐

