You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何在React Admin中渲染Firestore的自定义JSON嵌套数据

问题描述

我的数据来自Firestore数据库,此前基于Firestore测试集合创建多个Resource,运行效果良好。目前遇到问题:某集合仅含单个文档,其snapshot字段存储大体积JSON字符串,数据结构如下:

[
    {
        "id": "rj2PK96j3MashOA1AVFh",
        "timestamp": "2023-11-15T15:26:18.628Z",
        "snapshot": "{\"guests\": [{\"id\":\"41090\",\"id_transaction\":\"41755\",\"id_people\":\"33100\",\"status\":\"checkin\",\"paid_days_in_advance_to_partner\":\"2\",\"nights_to_pay\":\"13\",\"id_bed\":\"87\",\"id_key\":\"88\",\"room_type_id\":\"1\",\"original_checkout_plan\":\"2023-10-02\",\"checkout_plan\":\"2023-10-13\",\"checkout_confirmed\":{}}}",
        "updated": "2023-11-02T15:39:48.536Z",
        "domain": "testing"
    }
]

使用常规List/Datagrid/TextField组件可访问所有值,包括在React Admin列表中显示字符串化JSON,但希望snapshot字段渲染每个JSON键值对并保留组件能力。尝试解析snapshot后遍历guest用TextField渲染,控制台能获取数据但界面无内容,代码如下:

const SnapshotList = () => {  
  const { data, resource } = useListContext();  
  const snapshotString = data[0].snapshot;  
  try {  
    const snapshotJson = JSON.parse(snapshotString);  
    const todaysGuests = snapshotJson.assign_today.guests;  
    console.log("Todays Guests:", todaysGuests);  
    return (  
      <Datagrid>  
        {todaysGuests.map((guest: any, index: any) => (  
          <React.Fragment key={index}>  
            <TextField  
              label="Arrival Date"  
              source={`${guest}.arrival_date`}  
            />  
            <TextField  
              label="Reservation Code"  
              source={`${guest}.reservation_code`}  
            />  
            <TextField  
              label="Given Name"  
              source={`${guest}.given_name`}  
            />  
          </React.Fragment>  
        ))}  
      </Datagrid>  
    );  
  } catch (error) {  
    console.error("Error parsing JSON:", error);  
    return null;  
  }
};
export const Snapshots = () => (  
  <ResourceContextProvider value="snapshots">  
    <List pagination={<Pagination perPage={1000} rowsPerPageOptions={[]} />}>  
      <SnapshotList />  
    </List>  
  </ResourceContextProvider>
);

请问如何通过传递自定义资源给TextField组件生成对应Datagrid?


解决方案

问题核心在于React Admin的Datagrid和TextField的工作逻辑:Datagrid会自动遍历当前ListContext中的data数组生成行,TextField的source是当前行数据的属性路径,而非直接传入对象。以下是两种可行方案:

方案1:替换ListContext的数据源为解析后的guest数组

直接将解析出的todaysGuests作为新数据传入Datagrid,通过覆盖ListContext实现:

import { useListContext, Datagrid, TextField, ListContextProvider } from 'react-admin';

const SnapshotList = () => {  
  const { data, ...restContext } = useListContext();  
  try {  
    const snapshotString = data[0].snapshot;
    const snapshotJson = JSON.parse(snapshotString);  
    const todaysGuests = snapshotJson.guests; // 注意:需匹配实际JSON结构,示例中无assign_today层级
    console.log("Todays Guests:", todaysGuests);  

    return (
      <ListContextProvider value={{ ...restContext, data: todaysGuests }}>
        <Datagrid>  
          <TextField label="客人ID" source="id" />  
          <TextField label="交易ID" source="id_transaction" />  
          <TextField label="入住状态" source="status" />  
          <TextField label="需付晚数" source="nights_to_pay" />  
          <TextField label="原退房计划" source="original_checkout_plan" />  
        </Datagrid>  
      </ListContextProvider>
    );  
  } catch (error) {  
    console.error("JSON解析错误:", error);  
    return null;  
  }
};

方案2:手动渲染表格结构

如果不需要复用Datagrid的默认逻辑,可直接遍历解析后的guest数据自定义表格:

const SnapshotList = () => {  
  const { data } = useListContext();  
  try {  
    const snapshotString = data[0].snapshot;
    const snapshotJson = JSON.parse(snapshotString);  
    const todaysGuests = snapshotJson.guests;  

    return (
      <table style={{width: '100%', borderCollapse: 'collapse'}}>
        <thead>
          <tr style={{borderBottom: '1px solid #ddd'}}>
            <th style={{padding: '8px', textAlign: 'left'}}>客人ID</th>
            <th style={{padding: '8px', textAlign: 'left'}}>交易ID</th>
            <th style={{padding: '8px', textAlign: 'left'}}>入住状态</th>
            <th style={{padding: '8px', textAlign: 'left'}}>需付晚数</th>
          </tr>
        </thead>
        <tbody>
          {todaysGuests.map((guest, index) => (
            <tr key={index} style={{borderBottom: '1px solid #ddd'}}>
              <td style={{padding: '8px'}}>{guest.id}</td>
              <td style={{padding: '8px'}}>{guest.id_transaction}</td>
              <td style={{padding: '8px'}}>{guest.status}</td>
              <td style={{padding: '8px'}}>{guest.nights_to_pay}</td>
            </tr>
          ))}
        </tbody>
      </table>
    );  
  } catch (error) {  
    console.error("JSON解析错误:", error);  
    return null;  
  }
};

关键注意事项

  1. 数据结构匹配:示例snapshot中直接是guests数组,需根据实际JSON结构调整解析路径,若确实存在assign_today层级则保留snapshotJson.assign_today.guests
  2. TextField的source属性:使用Datagrid时,source是当前行数据的属性名,例如source="id"对应guest.id,无需拼接对象路径
  3. ListContext的作用:Datagrid依赖ListContext提供的data,替换上下文数据即可让Datagrid自动遍历guest数组

内容的提问来源于stack exchange,提问作者RodrigoCastro

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.06 02:10:57