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

Typescript搭配React-Aria开发Radio组件遇null无法赋值RadioGroupState错误

报错原因

你遇到的类型报错核心原因是 RadioContext 的默认值设为了 null,而 useRadio 钩子要求传入的状态参数必须是 RadioGroupState 类型,TypeScript 检测到从 Context 取出的 state 可能为 null,因此触发了类型校验失败。

具体修改方案

  1. 补充导入 RadioGroupState 类型,给 Context 明确类型定义
  2. 给 Radio 组件内的 Context 取值增加非空判断,既解决类型问题,也能避免开发者将 Radio 放在 RadioGroup 外使用的运行时错误

修改后的完整代码

import * as React from 'react';
import { VisuallyHidden } from '@react-aria/visually-hidden';
import { useFocusRing } from '@react-aria/focus';
import { useRadioGroup, useRadio } from '@react-aria/radio';
import { useRadioGroupState, RadioGroupState } from '@react-stately/radio';
import { AriaRadioGroupProps, AriaRadioProps } from '@react-types/radio';

// 给Context明确指定类型
let RadioContext = React.createContext<RadioGroupState | null>(null);

interface RadioGroupProps extends AriaRadioGroupProps {
  children: React.ReactNode;
}

interface RadioProps extends AriaRadioProps {
  children: React.ReactNode;
}

function RadioGroup(props: RadioGroupProps) {
  let { children, label } = props;
  let state = useRadioGroupState(props);
  let { radioGroupProps, labelProps } = useRadioGroup(props, state);

  return (
    <div {...radioGroupProps}>
      <span {...labelProps}>{label}</span>
      <RadioContext.Provider value={state}>{children}</RadioContext.Provider>
    </div>
  );
}

function Radio(props: RadioProps) {
  let { children } = props;
  let state = React.useContext(RadioContext);
  let ref = React.useRef<HTMLInputElement>(null);

  // 增加运行时校验,同时解决类型报错
  if (!state) {
    throw new Error('Radio 组件必须作为 RadioGroup 的子组件使用');
  }

  let { inputProps } = useRadio(props, state, ref);
  let { focusProps } = useFocusRing();

  let isSelected = state.selectedValue === props.value;
  const strokeWidth = 2;

  return (
    <label
      className={`${state.isDisabled ? 'cursor-not-allowed' : ''}`}
      style={{ display: 'flex', alignItems: 'center' }}
    >
      <VisuallyHidden>
        <input {...inputProps} {...focusProps} ref={ref} />
      </VisuallyHidden>
      <svg width={24} height={24} aria-hidden="true" style={{ marginRight: 4 }}>
        <circle
          cx={12}
          cy={12}
          r={8 - strokeWidth / 2}
          fill="none"
          stroke={isSelected ? 'red' : '#BBBBBB'}
          strokeWidth={strokeWidth}
        />
        {isSelected && (
          <path transform="translate(5.5 5)" d={`M 4 3 A 1 1 0 0 0 9 11 A 1 1 0 0 0 4 3`} fill="#F70000" />
        )}
      </svg>
      <div className={`${state.isDisabled ? 'text-grey-disabled cursor-not-allowed' : ''}`}>{children}</div>
    </label>
  );
}

export { Radio, RadioGroup };

如果你不需要运行时校验,也可以直接在取 Context 的时候加非空断言 let state = React.useContext(RadioContext)!; 快速解决类型报错。


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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 13:21:01