react-hook-form + chakra-ui + mana-mana pustaka nombor telefon (mungkin isu rujukan pertarungan)
P粉143640496
P粉143640496 2024-03-27 09:25:26
0
1
501

Saya menggunakan react-hook-form untuk membina komponen bentuk generik yang sangat bersarang dan dirujuk melalui paradigma useFormContext untuk membolehkan sarang komponen dalam sewenang-wenangnya. Saya menggunakan Chakra-UI untuk penggayaan. Ini semua berfungsi dengan baik. Walau bagaimanapun, saya ingin menambah input nombor telefon antarabangsa pada beberapa borang.

Saya sebenarnya tidak kisah perpustakaan mana yang saya gunakan asalkan ia berprestasi dalam konteks NextJS dan berfungsi dengan RHF dan Chakra, jadi saya terbuka kepada cadangan dalam arah yang berbeza daripada di bawah.

Saya rasa saya sangat hampir menggunakan react-international-phone.

Masalah yang saya hadapi (saya mengalami masalah yang sama tetapi berbeza sedikit dengan perpustakaan lain) ialah telefon react-international berfungsi dengan baik sama ada dengan Chakra atau react-hook-form, tetapi bukan kedua-duanya pada masa yang sama .

Dalam kod sumber Github, react-international-phone mempunyai contoh Buku Cerita yang disepadukan dengan Chakra-UI yang berfungsi seperti ini:

export const ChakraPhone = ({
  value,
  onChange,
}) => {
  const phoneInput = usePhoneInput({
    defaultCountry: 'us',
    value,
    onChange: (data) => {
      onChange(data.phone);
    },
  });

  return (
    <ChakraProvider>
        <Input
          value={phoneInput.phone}
          onChange={phoneInput.handlePhoneValueChange}
          ref={phoneInput.inputRef}
        />
    </ChakraProvider>
  );
};

Jika saya hanya menggunakan komponen Chakra Input dalam bentuk react-hook-bentuk ia akan kelihatan seperti ini:

<ConnectForm>
    {({ formState: { errors }, register}) => (
        <form>
            <FormControl isInvalid={errors.phone}>
                <FormLabel htmlFor='phone'>Phone Number</FormLabel>
                <Input
                  id='phone'
                  name='phone'
                  {...register('phone')} />
            </FormControl>
        </form>
    )}
</ConnectForm>

Dua isu yang menggabungkan dua perkara ini ialah ...register 返回 ref 到 html 输入,而 React-international-phone 需要将 onChange 作为属性传递给其 usePhoneInput cangkuk.

Untuk soalan pertama saya rasa saya boleh gunakan jawapan ini dan laksanakan

<Input
    value={phoneInput.phone}
    onChange={phoneInput.handlePhoneValueChange}
    name={name}
    ref={(el) => {reactHookRef(el); phoneInput.inputRef(el)}}
/>

Tetapi mengeluh phoneInput.inputRef 是一个对象而不是函数。事实上,文档说它是一个 React.RefObject<HTMLInputElement> ,这......我猜不是一个函数。但后来我不确定为什么 ref={phoneInput.inputRef} berfungsi dalam kod contoh.

Saya rasa saya boleh menyelesaikan masalah kedua dengan memfaktorkan semula bentuk cangkuk tindak balas register响应并将返回的onChange传递给usePhoneInputcangkuk.

Mulanya saya mencuba ini

const PhoneNumberInput = (props) => {
    return (    
        <ConnectForm>
            {({ formState: { errors }, register }) => {
                const { onChange, onBlur, name, ref: reactHookRef } = register('phone');
                const phoneInput = usePhoneInput({
                    defaultCountry: 'gb',
                    onChange: onChange
                })

                return (    
                    <ConnectForm>
                        <Input
                            type='tel'
                            value={phoneInput.phone}
                            onChange={phoneInput.handlePhoneValueChange}
                            name={name}
                            ref={(el) => {reactHookRef(el); phoneInput.inputRef}}
                        />

Tetapi masalahnya ialah usePhoneInput adalah cangkuk, jadi ia sebenarnya tidak boleh dipanggil di sana. Lokasi semasa saya ialah

const PhoneNumberInput = (props) => {
    const [ onChangeRHF, setOnChangeRHF ] = useState();

    const phoneInput = usePhoneInput({
        defaultCountry: 'gb',
        onChange: onChangeRHF
    })

    return (    
        <ConnectForm>
            {({ formState: { errors }, register }) => {
                const { onChange, onBlur, name, ref: reactHookRef } = register('phone');
                setOnChangeRHF(onChange);

                return (
                    <>
                        <InputGroup size={props?.size} id={props?.id || 'phone'}>
                            <InputLeftAddon width='4rem'>
                                <CountrySelector
                                    selectedCountry={phoneInput.country}
                                    onSelect={(country) => phoneInput.setCountry(country.iso2)}
                                    renderButtonWrapper={({ children, rootProps }) => 
                                        <Button {...rootProps} variant={'outline'} px={'4px'} mr={'8px'}>
                                            {children}
                                        </Button>
                                    }
                                />
                            </InputLeftAddon>
                        <Input
                            type='tel'
                            value={phoneInput.phone}
                            onChange={phoneInput.handlePhoneValueChange}
                            onBlur={onBlur}
                            name={name}
                            ref={(el) => {reactHookRef(el); phoneInput.inputRef}}
                        />

Saya rasa cukup dekat tetapi masih tidak berkesan. Saya telah memasukkannya ke dalam CodeSandbox. CodeSandbox rosak, dalam App.js saya mengulas panggilan ke borang kerana jika saya menyahkomennya ia akan mengunci penyemak imbas saya :(

Sebarang idea tentang cara menyambungkan react-hook-form dan chakra-ui dengan ini atau mana-mana perpustakaan nombor telefon lain?

P粉143640496
P粉143640496

membalas semua(1)
P粉680487967

Petua @adsy dalam komen menyelesaikan masalah.

Gunakan useController dalam komponen:

const PhoneNumberInput = ({ control, name, size='md' }) => {
    const {
        field,
        fieldState: { invalid, isTouched, isDirty },
        formState: { touchedFields, dirtyFields }
    } = useController({
        name,
        control
    })

    const phoneInput = usePhoneInput({
        defaultCountry: 'gb',
        onChange: (data) => {
            field.onChange(data.phone);
        }
    })

    return (
        
            
                
                     phoneInput.setCountry(country.iso2)}
                        renderButtonWrapper={({ children, rootProps }) => 
                            
                        }
                    />
                
                 field.ref(el) && phoneInput.inputRef}
                />
            
        >
    )
};

export default PhoneNumberInput;

(dan perubahan kecil kepada ref dalam komponen).

Kemudian apabila anda memanggilnya untuk bersarang dalam, juga pemusnahan control :


        {({ control, formState: { errors }, register}) => (
            
Phone Number {errors.phone && errors.phone.message}
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan