Skip to main content

useRadioGroup

useRadioGroup is a custom hook that provides all the state management logic for a group of radios.

Import

import { useRadioGroup } from '@chakra-ui/react'

Return value

The useRadioGroup hook returns following props

NameTypeDescription
valueStringOrNumber[]The value of radio group.
namestringThe name of the radio options. All radio options must use the same name.
refanyThe ref of the radio group.
isDisabledbooleanA utility to manage disabled state.
isFocusablebooleanA utility to manage focused state.
focus() => voidA utility function to set the focus on the first enabled radio.
onChange(nextValue: EventOrValue) => voidThe onChange handler for the radio group.
setValue(state: StringOrNumber[]) => voidA function to set the value of the radio group.
getRadioProps(props?: Dict) => DictA function that takes root props and handles changes for the radio group
getRootProps(props?: Dict) => DictA function that takes radio root props and handles changes for the radio group
htmlProps{}A function that takes radio root props and handles changes for the radio group

Usage

function Example() {
function CustomRadio(props) {
const { image, ...radioProps } = props
const { state, getInputProps, getCheckboxProps, htmlProps, getLabelProps } =
useRadio(radioProps)

return (
<chakra.label {...htmlProps} cursor='pointer'>
<input {...getInputProps({})} hidden />
<Box
{...getCheckboxProps()}
bg={state.isChecked ? 'green.200' : 'transparent'}
w={12}
p={1}
rounded='full'
>
<Image src={image} rounded='full' {...getLabelProps()} />
</Box>
</chakra.label>
)
}

const toast = useToast()

const avatars = [
{ name: 'Kat', image: 'https://randomuser.me/api/portraits/women/44.jpg' },
{ name: 'Kevin', image: 'https://randomuser.me/api/portraits/men/86.jpg' },
{ name: 'Andy', image: 'https://randomuser.me/api/portraits/men/29.jpg' },
{ name: 'Jess', image: 'https://randomuser.me/api/portraits/women/95.jpg' },
]

const handleChange = (value) => {
toast({
title: `The value got changed to ${value}!`,
status: 'success',
duration: 2000,
})
}

const { value, getRadioProps, getRootProps } = useRadioGroup({
defaultValue: 'Kevin',
onChange: handleChange,
})

return (
<Stack {...getRootProps()}>
<Text>The selected radio is: {value}</Text>
<HStack>
{avatars.map((avatar) => {
return (
<CustomRadio
key={avatar.name}
image={avatar.image}
{...getRadioProps({ value: avatar.name })}
/>
)
})}
</HStack>
</Stack>
)
}

Using isDisabled and isFocusable

When providing the hook with the isDisabled and/or isFocusable props, this values also need to be returned and passed to the radio inputs.

This is different than simply passing them as props to the RadioGroup component because the component has access to context to supply the values to the radio inputs.

Below is an example with isDisabled being passed to the hook and used with the Radio component. If needed, this custom component can than be controllable by a parent, which would supply the logic to determine if the inputs need to be disabled.

function CustomRadioGroup(props) {
const { options, ...rest } = props

const { getRootProps, getRadioProps, isDisabled } = useRadioGroup({
...rest,
})

const group = getRootProps()

return (
<HStack {...group}>
{options.map((value) => {
const radio = getRadioProps({ value })
return (
<Radio isDisabled={isDisabled} key={value} {...radio}>
{value}
</Radio>
)
})}
</HStack>
)
}

function Parent() {
const [isDisabled, setIsDisabled] = useState(true)

// Some logic to handle the disabled state

return (
<>
{/* Any components above */}
<CustomRadioGroup
isDisabled={isDisabled}
options={['react', 'vue', 'svelte']}
/>
{/* Any components below */}
</>
)
}

render(<Parent />)

Parameters

The useRadioGroup hook accepts an object with the following properties:

defaultValue

Description

The value of the radio to be checked initially (in uncontrolled mode)

Type
string | number

isDisabled

Description

If true, all wrapped radio inputs will be disabled

Type
boolean

isFocusable

Description

If true and isDisabled is true, all wrapped radio inputs will remain focusable but not interactive.

Type
boolean

isNative

Description

If true, input elements will receive checked attribute instead of isChecked. This assumes, you're using native radio inputs

Type
boolean

name

Description

The name attribute forwarded to each radio element

Type
string

onChange

Description

Function called once a radio is checked @param nextValue the value of the checked radio

Type
((nextValue: string) => void)

value

Description

The value of the radio to be checked (in controlled mode)

Type
string | number