0

I have a simple functional component which toggles the password field to and from visible via a small button which changes between closed and opened eye images.

There is no state affected in the parent, however, the parent un-mounts and re-mounts a split second after the image changes and this resets the child's isVisible state to false every time. Below is the code:

const Password = (props) => {
    
    const [isVisible, setIsVisible] = useState(false);
    
    const handleIsVisible = useCallback(() => setIsVisible(prev => !prev), []);

    return(
        <>
            <p className="EditProfileFieldLabel SubHeading">
                {(props.name === "password") ? "Password" : "Confirm Password"}
            </p>
            <div className="PasswordVisibleContainer">
                <button
                    className="PasswordVisibleBtn"
                    onClick={handleIsVisible}
                >
                    <img
                        src={(isVisible) ? passShowImg : passHideImg}
                        alt="Visible"
                    />
                </button>
            </div>
            <input
                className="Field LightGreenBG EditProfileFieldLong"
                name={props.name}
                placeholder="**********"
                onChange={props.handleOnChange}
                type={(isVisible) ? "text" : "password"}
            />
        </>
    );
}

Can anyone see something obvious that I'm missing? I don't think the parent should be re-mounting/re-rendering because of a child state change.

KTobiasson
  • 31
  • 6
  • He can't, only your parent's parent can unmount, I guess one of your props causes the parent to unmount, anyway this question is incomplete, see [How to create a Minimal, Reproducible Example](https://stackoverflow.com/help/minimal-reproducible-example) – Dennis Vash Aug 02 '21 at 17:10
  • I appreciate your comment @DennisVash, however, I don't agree that my question is not complete. The parent was clearly un-mounting/re-mounting and no props or state changes happened in the parent as I mentioned in my original question. The fix that I found, and included below, did not include a single change to the parent. I only changed the child function shown in my example by including a key which contained the state variable. – KTobiasson Aug 02 '21 at 17:30
  • You can and should add add the key from the parent component – Dennis Vash Aug 02 '21 at 17:39
  • Thanks again @DennisVash, but I don't see how adding the "key" from the parent component would help here. Please elaborate... – KTobiasson Aug 02 '21 at 18:21

1 Answers1

0

I added a key to the outer element of the child and included the isVisible state variable within that key and everything was good to go.

*EDIT: The reason that this happened is because the button was submitting the form. So the correct fix is to change the button type property from its default value of "submit" to "button". After doing this, there was no need for the previous fix of adding the key with the state variable.

Working code below:

const Password = (props) => {
    
    const [isVisible, setIsVisible] = useState(false);
    
    const handleIsVisible = useCallback(() => setIsVisible(prev => !prev), []);

    return(
        <div key={`Password${props.name + isVisible}`}>
            <p className="EditProfileFieldLabel SubHeading SmlHeading">
                {(props.name === "password") ? "Password" : "Confirm Password"}
            </p>
            <div className="PasswordVisibleContainer">
                <button
                    className="PasswordVisibleBtn"
                    onClick={handleIsVisible}
                    type="button"
                >
                    <img
                        src={(isVisible) ? passShowImg : passHideImg}
                        alt="Visible"
                    />
                </button>
            </div>
            <input
                className="Field LightGreenBG EditProfileFieldLong"
                name={props.name}
                placeholder="**********"
                onChange={props.handleOnChange}
                type={(isVisible) ? "text" : "password"}
            />
        </div>
    );
}
KTobiasson
  • 31
  • 6