Strapi+React中Material UI DataGrid嵌套节点显示异常问题
解决Material UI DataGrid嵌套节点显示与Contact模态框Undefined问题
问题根源分析
- DataGrid Leads列显示异常:你在
columns配置中为leads列写了冗余且错误的valueGetter——转换companies数据时,已经将leads数组处理成字符串并挂载到row对象上,但valueGetter仍尝试从params.row.attributes取值(此时row里已无attributes字段)。 - Contact模态框值为Undefined:若使用Strapi v4,关联字段(如
contact)返回结构为{ data: { attributes: {...} } },你直接取params.row.contact拿到的是外层容器对象,而非真正的属性数据;同时你的GraphQL查询可能未遵循Strapi v4的关联字段嵌套规则(需遍历data和attributes)。
修正后的完整代码
import React, { useState } from 'react'; import { useQuery } from '@apollo/client'; import { DataGrid } from '@material-ui/data-grid'; import { Modal, Typography, Box, List, ListItem, ListItemText } from '@material-ui/core'; import ReactMarkdown from 'react-markdown'; import gql from 'graphql-tag'; // 适配Strapi v4的GraphQL查询结构(使用v3可忽略此调整) const GET_COMPANIES_QUERY = gql` query { companies { data { id attributes { companyName status internship futureMinEmp futureMaxEmp leads { data { attributes { leadSourceName } } } contact { data { attributes { firstName lastName jobtitle lastContact nextContact notes { data { attributes { date note } } } } } } } } } } `; const columns = [ { field: 'companyName', headerName: 'Company Name', flex: 1, headerAlign: 'center' }, { field: 'status', headerName: 'Status', flex: 1, headerAlign: 'center' }, { field: 'internship', headerName: 'Internship', flex: 1, headerAlign: 'center' }, { field: 'futureMinEmp', headerName: 'Min Employees', flex: 1, headerAlign: 'center' }, { field: 'futureMaxEmp', headerName: 'Max Employees', flex: 1, headerAlign: 'center' }, // 移除错误的valueGetter,直接使用处理好的leads字段 { field: 'leads', headerName: 'Leads', flex: 1, headerAlign: 'center' }, ]; const CompaniesPage = () => { const [selectedContact, setSelectedContact] = useState(null); const { loading, error, data } = useQuery(GET_COMPANIES_QUERY); if (loading) return <p>Loading...</p>; if (error) return <p>Error :(</p>; const companies = data?.companies?.data?.map((company) => { // 处理Leads数据(适配Strapi v4结构) const leadList = company.attributes?.leads?.data || []; const leads = leadList.length > 0 ? leadList.map(lead => lead.attributes.leadSourceName).join(', ') : 'No leads'; // 处理Contact数据(提取真正的属性对象) const contactData = company.attributes?.contact?.data?.attributes || null; // 处理Notes数据(转换为属性数组) if (contactData) { contactData.notes = contactData.notes?.data?.map(note => note.attributes) || []; } return { id: company.id, ...company.attributes, leads, contact: contactData, // 挂载处理后的contact对象 }; }); const handleRowClick = (params) => { setSelectedContact(params.row.contact); }; const handleCloseModal = () => { setSelectedContact(null); }; return ( <> <DataGrid rows={companies} columns={columns} autoHeight onRowClick={handleRowClick} getRowClassName={(params) => params.row.contact ? 'clickable-row' : ''} /> <Modal open={!!selectedContact} onClose={handleCloseModal} style={{ display: 'flex', alignItems: 'center', justifyContent: 'center' }} > <Box bgcolor="background.paper" boxShadow={2} p={3} style={{ outline: 'none', minWidth: 400 }}> {selectedContact ? ( <> <Typography variant="h4" gutterBottom> {selectedContact.firstName} {selectedContact.lastName} </Typography> <Typography variant="subtitle1" gutterBottom> {selectedContact.jobtitle} </Typography> <Typography variant="subtitle2" gutterBottom> Last Contact: {selectedContact.lastContact} </Typography> <Typography variant="subtitle2" gutterBottom> Next Contact: {selectedContact.nextContact} </Typography> <Typography variant="h6" gutterBottom style={{ marginTop: 16 }}> Notes </Typography> <List> {selectedContact.notes.length > 0 ? ( selectedContact.notes.map((note, index) => ( <ListItem key={index}> <ListItemText primary={note.date} secondary={<ReactMarkdown>{note.note}</ReactMarkdown>} /> </ListItem> )) ) : ( <Typography variant="body2">No notes available</Typography> )} </List> </> ) : null} </Box> </Modal> </> ); }; export default CompaniesPage
关键修改说明
- GraphQL查询修正:针对Strapi v4关联字段结构,补充
data和attributes层级,确保正确获取嵌套数据。 - Leads列配置简化:移除错误的
valueGetter,直接使用转换后的leads字符串字段。 - Contact数据处理:从Strapi返回的关联结构中提取真正的属性对象,确保模态框能读取
firstName等字段。 - Notes数据转换:将Notes的嵌套结构转换为属性数组,方便在模态框中遍历展示。
- 模态框优化:增加Notes列表展示,完善空状态处理,移除不必要的
event.preventDefault()(Modal关闭无需阻止默认行为)。
内容的提问来源于stack exchange,提问作者user2371684
相关产品推荐
相关产品推荐

