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

React中setCountry无法更新默认国家下拉选项问题求助

下拉选择框默认值不生效问题解决方法

我需要给下拉选择框设置默认国家选项,选项包括United States、United Kingdom和Rest of the world,对应的可用国家常量如下:

const AVAILABLE_COUNTRIES: PartialDeep<Country[]> = [
  {
    isoCode: 'GB' as CountryCode,
    name: 'United Kingdom',
    currency: {
      isoCode: 'GBP' as CurrencyCode,
    },
  },
  {
    isoCode: 'US' as CountryCode,
    name: 'United States',
    currency: {
      isoCode: 'USD' as CurrencyCode,
    },
  },
];

当前遇到的问题:页面渲染时下拉框没有默认选中任何值,但直接将const [country, setCountry] = useState('');改为const [country, setCountry] = useState('us');时,下拉框能正常显示United States作为默认选项。


问题原因

  1. useForm的defaultValues仅在组件初始化时生效一次,初始country为空字符串,后续通过useEffect异步获取国家后更新的country状态,无法自动同步到表单中。
  2. 虽然给FormFieldSelect传了defaultValue={country},但react-hook-form的register方法会接管表单控件状态,defaultValue会被表单初始值覆盖,异步更新的值无法生效。

解决方案

方案一:用react-hook-form的setValue同步异步值

修改useEffect逻辑,在获取到匹配国家后,同时更新组件状态和表单字段值:

const [country, setCountry] = useState('');
const getCountryFromCode = useCallback((code: CountryCode) => {
  const selected = AVAILABLE_COUNTRIES.find(
    (country) => country?.isoCode === code.toUpperCase(),
  );
  return selected ? selected.isoCode?.toLowerCase() : 'row';
}, []);

const {
  formState: {errors, isDirty, isSubmitting, isSubmitSuccessful},
  handleSubmit,
  register,
  setError,
  setValue, // 新增:获取setValue方法
} = useForm<
  FormValues & {
    serverError?: string;
  }
>({
  defaultValues: {
    name: '',
    email: '',
    number: '',
    type: 'trade',
    country: '', // 初始值设为空或兜底值'row'
    message: '',
  },
  resolver: yupResolver(schema),
});

useEffect(() => {
  const fetchUserCountry = async () => {
    try {
      const response = await fetch('https://ipinfo.io?token=d0f95sdfdsfdsfxxx');
      const data = await response.json();

      if (data.country) {
        const userCountry = data.country;
        const matchingCountry = getCountryFromCode(userCountry);
        if (matchingCountry) {
          setCountry(matchingCountry);
          setValue('country', matchingCountry); // 同步到表单字段
          console.log(matchingCountry);
        }
      }
    } catch (error) {
      console.error('Error occurred while fetching user country:', error);
    }
  };

  fetchUserCountry();
}, [getCountryFromCode, setValue]); // 把setValue加入依赖数组

方案二:等待国家获取完成后再初始化表单

如果页面允许等待国家信息加载后再渲染表单,可以通过加载状态控制渲染时机:

const [country, setCountry] = useState<string | null>(null);
const [isLoading, setIsLoading] = useState(true);
const getCountryFromCode = useCallback((code: CountryCode) => {
  const selected = AVAILABLE_COUNTRIES.find(
    (country) => country?.isoCode === code.toUpperCase(),
  );
  return selected ? selected.isoCode?.toLowerCase() : 'row';
}, []);

useEffect(() => {
  const fetchUserCountry = async () => {
    try {
      const response = await fetch('https://ipinfo.io?token=d0f95sdfdsfdsfxxx');
      const data = await response.json();

      if (data.country) {
        const userCountry = data.country;
        const matchingCountry = getCountryFromCode(userCountry);
        setCountry(matchingCountry);
      } else {
        setCountry('row'); // 无匹配时的兜底默认值
      }
    } catch (error) {
      console.error('Error occurred while fetching user country:', error);
      setCountry('row'); // 出错时的兜底默认值
    } finally {
      setIsLoading(false);
    }
  };

  fetchUserCountry();
}, [getCountryFromCode]);

// 等待加载完成后再初始化表单
if (isLoading) {
  return <div>Loading...</div>;
}

const {
  formState: {errors, isDirty, isSubmitting, isSubmitSuccessful},
  handleSubmit,
  register,
  setError,
} = useForm<
  FormValues & {
    serverError?: string;
  }
>({
  defaultValues: {
    name: '',
    email: '',
    number: '',
    type: 'trade',
    country: country!, // 直接使用已获取到的country值
    message: '',
  },
  resolver: yupResolver(schema),
});

额外注意点

  • 检查FormFieldSelect中的空选项:组件内有一个value=""的禁用选项,若表单字段值为空会选中该选项,确保异步获取的值是gb/us/row中的有效选项值。
  • 确认getCountryFromCode返回值与选项value完全匹配,当前代码中toLowerCase()处理已保证格式一致,无需额外修改。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.16 18:32:01