Typescript搭配React-Aria开发Radio组件遇null无法赋值RadioGroupState错误
报错原因
你遇到的类型报错核心原因是 RadioContext 的默认值设为了 null,而 useRadio 钩子要求传入的状态参数必须是 RadioGroupState 类型,TypeScript 检测到从 Context 取出的 state 可能为 null,因此触发了类型校验失败。
具体修改方案
- 补充导入
RadioGroupState类型,给 Context 明确类型定义 - 给 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
相关产品推荐
相关产品推荐

