Skip to content

Instantly share code, notes, and snippets.

@dohomi
Last active January 6, 2023 04:30
Show Gist options
  • Star 1 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save dohomi/4bcbf1eb51e93baea8ccb19a6d4ac066 to your computer and use it in GitHub Desktop.
Save dohomi/4bcbf1eb51e93baea8ccb19a6d4ac066 to your computer and use it in GitHub Desktop.
phone number field with react-hook-form and Material-UI
import { RegisterOptions, useController } from 'react-hook-form'
import { TextField, TextFieldProps } from '@material-ui/core'
import { forwardRef, useEffect, useRef } from 'react'
import PhoneInput from 'react-phone-number-input/input-mobile'
import useLmTranslation from '../../../lib/hooks/useLmTranslation'
type LmTextFieldFormProps = TextFieldProps & {
name: `${string}.${string}` | `${string}.${number}` | `${string}`
rules?: Exclude<
RegisterOptions,
'valueAsNumber' | 'valueAsDate' | 'setValueAs'
>
}
function LmPhoneNumberFieldForm({
name,
rules,
helperText,
...rest
}: LmTextFieldFormProps): JSX.Element {
const { t } = useLmTranslation()
const ForwardInputComponent = forwardRef((props, ref) => {
// @ts-ignore
const currentValue = props.value
const rendered = useRef<boolean>() // to grab the default value
const {
fieldState: { invalid },
field: { onChange, value }
} = useController({
name,
rules
})
useEffect(() => {
if (rendered.current) {
onChange(currentValue) // don't call on initial render due to defaultValue
}
rendered.current = true
}, [onChange, currentValue, rendered])
return (
<TextField
{...rest}
{...props}
name={name}
value={currentValue || value}
helperText={invalid ? t('error.required') : helperText}
error={invalid}
required={!!rules?.required}
inputRef={ref}
/>
)
})
return (
<PhoneInput
onChange={(val) => {
if (typeof rest.onChange === 'function') {
rest.onChange(val)
}
}}
inputComponent={ForwardInputComponent}
/>
)
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment