I'm trying to build a design-system in Typescript using React-Aria and I am having some trouble with the Radio component.
I tried to follow the example as much as I could but I ended up with: Argument of type 'null' is not assignable to parameter of type 'RadioGroupState'.
And I don't understand how to solve this issue, does someone have some advice for me?
Here's my code:
import { VisuallyHidden } from '@react-aria/visually-hidden';
import { useFocusRing } from '@react-aria/focus';
import { useRadioGroup, useRadio } from '@react-aria/radio';
import { useRadioGroupState } from '@react-stately/radio';
import { AriaRadioGroupProps } from '@react-types/radio';
import { AriaRadioProps } from '@react-types/radio';
let RadioContext = React.createContext(null);
interface RadioGroupProps extends AriaRadioGroupProps {
children: React.ReactNode;
}
interface RadioProps extends AriaRadioProps {
children: React.ReactNode;
}
function RadioGroup(props: RadioGroupProps) {
let { children, label, isDisabled, defaultValue } = 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(null);
let { inputProps } = useRadio(props, state, ref);
let { isFocusVisible, focusProps } = useFocusRing();
let isSelected = state.selectedValue === props.value;
let strokeWidth = isSelected ? 2 : 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 };
I solved the problem this way:
RadioGroupState
from @react-stately/radio
.let RadioContext = createContext<RadioGroupState | null>(null);
null
possibility:let stateOrNull = useContext(RadioContext);
state
variable and casted it to the RadioGroupState
type:let state = stateOrNull as RadioGroupState;
import { createContext, useContext, useRef } from "react";
import { VisuallyHidden } from "@react-aria/visually-hidden";
import { useFocusRing } from "@react-aria/focus";
import { useRadioGroup, useRadio } from "@react-aria/radio";
import { RadioGroupState, useRadioGroupState } from "@react-stately/radio";
import { AriaRadioGroupProps, AriaRadioProps } from "@react-types/radio";
let RadioContext = 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 stateOrNull = useContext(RadioContext);
let state = stateOrNull as RadioGroupState;
let ref = useRef(null);
let { inputProps } = useRadio(props, state, ref);
let { focusProps } = useFocusRing();
let isSelected = state.selectedValue === props.value;
let strokeWidth = isSelected ? 2 : 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 };
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.