goveo / react-international-phone

☎️ International phone input component for React
https://react-international-phone.vercel.app/
MIT License
288 stars 54 forks source link

Flickering value and placeholder during re-rendering #28

Closed Riyad-Arafat closed 1 year ago

Riyad-Arafat commented 1 year ago

I'm writing to report a bug I encountered while using the "react-international-phone" package. The issue is related to the placeholder value that is being displayed every time the component re-renders.

Specifically, when the component has a value, the placeholder is displayed briefly before the actual value is shown. This behavior occurs every time the component re-renders, causing a noticeable flicker.

I have tried to address this issue on my end, but without success. I would like to request your assistance in resolving this problem. I'm happy to provide any additional information or to assist in any way I can.

The following snippet produces the issue.

import React from "react";
import { useTranslation } from "react-i18next";

import { Form, FormItemProps } from "antd";
import {
  PhoneInput as Input,
  PhoneInputProps,
} from "react-international-phone";
import "react-international-phone/style.css";

const PhoneInput: React.FC<PhoneInputProps & FormItemProps> = React.memo(
  ({ ...props }) => {
    const { t } = useTranslation("validation");
    const form = Form.useFormInstance();
    const value = Form.useWatch(props?.name || "");

    const onChange = (data: string) => {
      if (!data) return;
      if (!!props.name) form.setFieldValue(props.name, data);
    };

    const style = () => {
      if (!!props.disabled)
        return {
          backgroundColor: "rgba(0, 0, 0, 0.04)",
          color: "rgba(0, 0, 0, 0.25)",
        };
      return {};
    };

    return (
      <Input
        {...props}
        placeholder={`${t("placeholders.phone_number")}`}
        initialCountry="nl"
        value={value}
        onChange={onChange}
        inputStyle={style()}
      />
    );
  }
);

export default PhoneInput;
goveo commented 1 year ago

@riyadelberkawy Hey, I can't reproduce placeholder flickering on rerender. I have created a sandbox with provided code snipped: https://codesandbox.io/s/blazing-sunset-zk7dw4

Please, check if you can see flickering in this example. (or modify this sandbox to reproduce the bug you encountered if you have a chance :pray:)

Riyad-Arafat commented 1 year ago

@goveo Hi, I modified the sandbox you provided and was able to reproduce the issue. You can see it here: https://codesandbox.io/s/quizzical-golick-1241hk To reproduce the issue, you need to re-rendering the entire form by toggling the visibility of the form by clicking on the show and hide buttons. Let me know if you need anything else to help diagnose this problem. Thank you!

goveo commented 1 year ago

@riyadelberkawy Should be fixed in version 1.8.4 https://codesandbox.io/s/admiring-edison-zsogwo

Please provide any feedback if the issue still persists

Riyad-Arafat commented 1 year ago

@goveo Thank you for fixing the issue πŸ₯³ I have tested the changes in the provided codesandbox and it seems to be working as expected. I appreciate your prompt response and effort in resolving the issue. Let me know if there's anything else I can do to assist. Thank you again!

Riyad-Arafat commented 1 year ago

@goveo Sorry about that but I noticed that the issue occurs again when I add an initial value for the phone field in the form. https://codesandbox.io/s/quizzical-golick-1241hk

goveo commented 1 year ago

That happened because useWatch returns undefined on the first render. You can simply add a check for undefined: https://codesandbox.io/s/eager-proskuriakova-vv3kr2?file=/src/PhoneInput.tsx:607-639

Also, the country guessing on the initial render was slightly fixed in version 1.8.5, so I have updated the example to it. Can you check if this solved your problem, please?

goveo commented 1 year ago

@riyadelberkawy UPD: I have changed the usage of Form.useWatch to just form.getFieldValue and everything seems like work as expected:

const value = Form.useWatch(props?.name || "");

to

const value = form.getFieldValue(props?.name || "");
Riyad-Arafat commented 1 year ago

@goveo it's working properly now. πŸŽ‰ Thanks for your effort.

goveo commented 1 year ago

πŸŽ‰ Thank you for your effort!
⭐ Consider leaving a star on this repo if you like the project.