React-Admin:传递数据至Edit组件前如何适配TranslatableInputs?
解决React-Admin中TranslatableInputs与现有数据结构不匹配的问题
你的核心问题是后端返回的数据结构和TranslatableInputs期望的格式不兼容,只需在数据进入表单前做格式转换,提交时再转回去即可,以下是两种可行方案:
方案1:用Edit组件的transform属性处理双向转换
利用Edit组件的transform属性处理读取数据时的格式转换,再通过mutationOptions.transform处理提交时的逆向转换,无需额外组件:
<Edit // 读取后端数据时,转换成TranslatableInputs需要的格式 transform={data => ({ ...data, // 从translations中提取name字段,整理为{ locale: value }结构 name: Object.fromEntries( Object.entries(data.translations).map(([locale, values]) => [locale, values.name || '']) ), // 同理处理synonyms字段 synonyms: Object.fromEntries( Object.entries(data.translations).map(([locale, values]) => [locale, values.synonyms || '']) ), // 移除原translations字段避免冲突 translations: undefined, })} mutationOptions={{ // 提交表单时,把数据转回后端需要的translations结构 transform: (formData) => ({ ...formData, translations: Object.fromEntries( Object.entries(formData.name).map(([locale, name]) => [ locale, { name, synonyms: formData.synonyms[locale] || '' } ]) ), // 移除TranslatableInputs生成的临时字段 name: undefined, synonyms: undefined, }), }} > <SimpleForm> <TextInput source="color" type="color" sx={{minWidth: 100}} /> <Box sx={{width: "50%", maxWidth: "100%"}} > <TranslatableInputs locales={["en", "es", "de"]}> <TextInput source="name" fullWidth /> <TextInput source="synonyms" multiline fullWidth/> </TranslatableInputs> </Box> </SimpleForm> </Edit>
方案2:自定义包装组件实现数据映射
如果需要更灵活的字段控制,可以自定义一个包装组件,结合useForm钩子处理数据初始化映射:
import { useForm, TranslatableInputs } from 'react-admin'; import React from 'react'; const TranslatableDataAdapter = ({ children, locales, translations }) => { const { form } = useForm(); // 组件挂载时,将translations转换为TranslatableInputs兼容格式并更新表单 React.useEffect(() => { if (!translations) return; const mappedFields = {}; React.Children.forEach(children, child => { const source = child.props.source; if (source) { mappedFields[source] = Object.fromEntries( Object.entries(translations).map(([locale, values]) => [locale, values[source] || '']) ); } }); form.mutate(mappedFields, { shouldValidate: false }); }, [translations, form, children]); return <TranslatableInputs locales={locales}>{children}</TranslatableInputs>; }; // 在Edit中使用自定义组件 <Edit mutationOptions={{ transform: (formData) => ({ ...formData, translations: Object.fromEntries( Object.entries(formData.name).map(([locale, name]) => [ locale, { name, synonyms: formData.synonyms[locale] || '' } ]) ), name: undefined, synonyms: undefined, }), }} > <SimpleForm> <TextInput source="color" type="color" sx={{minWidth: 100}} /> <Box sx={{width: "50%", maxWidth: "100%"}} > <TranslatableDataAdapter locales={["en", "es", "de"]} translations={record?.translations}> <TextInput source="name" fullWidth /> <TextInput source="synonyms" multiline fullWidth/> </TranslatableDataAdapter> </Box> </SimpleForm> </Edit>
注意事项
- 代码中添加了
|| ''做容错处理,避免locale字段缺失导致表单报错 - 提交转换逻辑需覆盖所有
TranslatableInputs中的字段,确保数据完整
内容的提问来源于stack exchange,提问作者Code Spirit
相关产品推荐
相关产品推荐

