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

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.08.10 15:15:43