I have a react component with four ref objects as below.
const lastNameRef = useRef<HTMLInputElement>(null);
const firstNameRef = useRef<HTMLInputElement>(null);
const emailRef = useRef<HTMLInputElement>(null);
const passwordRef = useRef<HTMLInputElement>(null);
i also have a different button component that takes in a disabled flag as a prop.
<SignInOrSignUpButton
disabled={false}
icon={faGear}
isLoading={isLoading}
onClick={handleSignUp}
text="Create Account"
/>
I’m trying to disable the button when any of my inputs are empty. Here is what i tried first
I tried checking if any of the inputs value
s length is 0 implying the input is empty. This didn’t work
<SignInOrSignUpButton
disabled={
lastNameRef.current?.value.length === 0 ||
firstNameRef.current?.value.length === 0 ||
emailRef.current?.value.length === 0 ||
passwordRef.current?.value.length === 0
}
icon={faGear}
isLoading={isLoading}
onClick={handleSignUp}
text="Create Account"
/>
I also tried the useState useEffect combination but that also didn’t work.
useEffect(() => {
if (
lastNameRef.current?.value.length === 0 ||
firstNameRef.current?.value.length === 0 ||
emailRef.current?.value.length === 0 ||
passwordRef.current?.value.length === 0
) {
setIsButtonDisabled(true);
} else {
setIsButtonDisabled(false);
}
}, [
lastNameRef.current?.value,
firstNameRef.current?.value,
emailRef.current?.value,
passwordRef.current?.value,
]);
<SignInOrSignUpButton
disabled={isButtonDisabled}
icon={faGear}
isLoading={isLoading}
onClick={handleSignUp}
text="Create Account"
/>
Please help.
2
Answers
Your code doesn’t work because React doesn’t re-render your component.
useRef
is used as a plain javascript object that persists between renders, but changing it doesn’t cause a re-render as modifying any nested properties.I would go with simple states to achieve whatever you are trying, converting the inputs from uncontrolled to controlled input.
Here are the official React docs about this topic.
The issue here is that updating
ref
s doesn’t cause the component to re-render and the three different approaches you took would require the component to re-render in order to display the button as disabled.Although the docs recommend using refs just as an "escape hatch", if you are forced to keep using
ref
s instead of state. Add another ref for thebutton
.Create a function to change the
disabled
attribute for thebutton
:So each
<input>
will update thebuttonRef
when there’s a change. Example:Create a function to return true/false to set the initial disabled value for the button
Pass the
buttonRef
ref to your button component. Note: since you’re using your own function component you will have to useforwardRef
within the component to pass thebuttonRef