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

Mui TextField刷新时值与占位符同时显示的问题求助

问题:MUI TextField在刷新页面时同时显示值和占位符

在表单编辑模式下刷新页面时,MUI TextField组件中会同时显示值和占位符。以下是相关代码:

表单组件

const Form = () => {
  // fetch hook to get the settings data.
  const settings = useGetSettingsQuery();
  // initialize the useFormik hook with the data just fetched
  const form = useSettingsForm({ initialValues: settings.data?.data ?? {} });

  return (
    <Box>
      <Grid container spacing={2}>
         <Grid item xs={12}>
          <TextField
            fullWidth
            name={'id'}
            label={'id'}
            placeholder={'ticket id'}
            variant="outlined"
            value={form.values.id}
            onChange={form.handleChange}
          />
        </Grid>
        <Grid item xs={12}>
          initial values
          <pre>{JSON.stringify({ id: form.initialValues.id }, null, 2)}</pre>
        </Grid>
        <Grid item xs={12}>
          current value values
          <pre>{JSON.stringify({ id: form.values.id }, null, 2)}</pre>
        </Grid>
      </Grid>
    </Box>
  );
};

自定义hook

export const useSettingsForm = ({ initialValues }: Props) => {
  return useFormik<Partial<ISetting>>({
    enableReinitialize: true,
    initialValues: {
      ...initialValues,
    },
    validationSchema: Yup.object().shape({}),
    onSubmit: async (values) => {
      console.log('submitted -> ', values);
    },
  });
};

RTK Query的apiSlice片段

export const settingApiSlice = apiSlice.injectEndpoints({
  endpoints(builder) {
    return {
      getSettings: builder.query<IGetSettingsResp, void>({
        query() {
          return `/setting`;
        },
        providesTags: ['setting'],
      }),
    };
  },
});

export const { useGetSettingsQuery } = settingApiSlice;

原因分析

问题核心是异步数据加载的时序异常:

  1. 页面刷新后,RTK Query请求先处于pending状态,此时settings.data为undefined,Formik初始值为空对象,form.values.id是undefined。
  2. MUI TextField在value为undefined时,会判定为未受控状态,此时占位符显示,label停留在输入框内部。
  3. 数据加载完成后,enableReinitialize触发Formik更新值,但如果返回的id是空字符串,或组件状态同步不及时,就会出现值与占位符同时显示的情况。
  4. 受控组件的value需始终为字符串类型,传递undefined会导致组件行为异常。

解决方案

方案1:确保TextField的value始终为字符串

将TextField的value设置为兜底空字符串,避免传递undefined:

<TextField
  fullWidth
  name={'id'}
  label={'id'}
  placeholder={'ticket id'}
  variant="outlined"
  value={form.values.id ?? ''} // 确保值为字符串类型
  onChange={form.handleChange}
/>

方案2:处理异步加载状态,延迟渲染表单

在数据加载完成前显示加载提示,避免渲染未就绪的输入框:

const Form = () => {
  const settings = useGetSettingsQuery();

  // 数据加载中时显示加载状态
  if (settings.isLoading) {
    return <Box>加载中...</Box>;
  }

  const form = useSettingsForm({ initialValues: settings.data?.data ?? {} });

  return (
    // 原表单内容
  );
};

方案3:初始化Formik时设置默认空字符串

在自定义hook中给id字段设置默认空字符串,避免初始值为undefined:

export const useSettingsForm = ({ initialValues }: Props) => {
  return useFormik<Partial<ISetting>>({
    enableReinitialize: true,
    initialValues: {
      id: '', // 设置默认空字符串
      ...initialValues,
    },
    validationSchema: Yup.object().shape({}),
    onSubmit: async (values) => {
      console.log('submitted -> ', values);
    },
  });
};

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.31 20:01:33