We have an input field that's a react component (based on MUI TextField). We want to validate the input when the user leaves the field and, if it's incorrect, set the focus back to that field. Currently the component is set up like this:
<TextBox
className="phone-data"
value={phone}
onChange={(e) => setPhone(e.target.value)}
onBlur={() => {
if (!validatePhone(phone)) {
alert('Phone number is not valid')
setPhone('');
}
}}>
</TextBox>
The TextBox component is defined like this:
const TextBox = ({ className, label, onChange, type, value, width, onBlur, children }) => {
return (
<TextField
sx={{
'& .MuiOutlinedInput-root': {
'& > fieldset': { borderColor: 'gray' },
},
'minWidth': width,
'bgcolor': '#1a1a1a',
}}
variant="outlined"
size="small"
className={className}
type={type}
label={label}
onChange={onChange}
onBlur={onBlur}
value={value}
>
{children}
</TextField>
);
};
After the setPhone('')
call in the onBlur handler of TextBox, we want the focus to stay on the TextBox, and not go to whatever the user clicked on. From what we've found so far it seems to have something to do with refs, but ref is not a field of MUI TextField. Thanks.
CodePudding user response:
you need to first change your TextBox component to have ref like this:
const TextBox = React.forwardRef(({ className, label, onChange, type, value, width, onBlur, children },ref) => {
return (
<TextField
ref={ref}
sx={{
'& .MuiOutlinedInput-root': {
'& > fieldset': { borderColor: 'gray' },
},
'minWidth': width,
'bgcolor': '#1a1a1a',
}}
variant="outlined"
size="small"
className={className}
type={type}
label={label}
onChange={onChange}
onBlur={onBlur}
value={value}
>
{children}
</TextField>
);
});
and then you need to change the call of the component as this:
const textBoxRef = useRef();
<TextBox
className="phone-data"
ref={textBoxRef}
value={phone}
onChange={(e) => setPhone(e.target.value)}
onBlur={() => {
if (!validatePhone(phone)) {
alert('Phone number is not valid')
setPhone('');
textBoxRef.current.focus();
}
}}>
</TextBox>
CodePudding user response:
In functional components, you need to use
React.forwardRef
.
Similar to how we could tap into HTMLElement's DOM properties using ref, we can also create ref property for higher order components such as your TextBox
component, by forwarding the ref.
I've created a minimalist example similar to your without bells and whistles. Check this out. https://codesandbox.io/embed/epic-panini-wmy9zu
For complete documentation, check this from React site. It would prove to be useful. https://reactjs.org/docs/forwarding-refs.html