I have a custom pin input of 5 input fields. My goal is to have control of the next input via reference. so I can perform an action like reference.focus()
or reference.unfocus()
.
Presently my code looks like this:
const PinInput = ({ ...props }: Props): JSX.Element => {
const [value, setValue] = useState<Array<string>>(Array.from({ length: 6 }, () => ''));
const inputRef = React.useRef<HTMLInputElement>(null);
return (
<Box sx={{ display: 'flex', justifyContent: 'space-between', flexDirection: 'row' }}>
{_.times(6, (i) => (
<TextField
key={i.toString()}
id={i.toString()}
className="pinError"
placeholder={props.placeholder}
sx={{
borderRadius: '4px',
}}
inputRef={inputRef}
inputProps={{
inputMode: 'numeric',
size: 3,
maxLength: 1,
style: {
color: colors.errorDefault,
textAlign: 'center',
backgroundColor: colors.error80,
caretColor: colors.transparent,
},
}}
required
value={value[i]}
onKeyDown={(event) => {
if (event.key === 'Backspace') { console.log(event.key); }
}}
onChange={(event) => {
value[i] = event.target.value;
setValue([...value]);
inputRef?.current?.focus();
if (props.onChange) props.onChange(event);
}}
/>
))}
</Box>
);
};
But the issue is now, I have only one inputRef
for all the input pins. how can I make this dynamic. I tried this:
const refs = Array.from({ length: 6 }, () => React.useRef<HTMLInputElement>(null));
but was met with the error: React Hook "React.useRef" cannot be called inside a callback.
CodePudding user response:
You need to create an array of Refs to manage all your inuts separately. Here is a repro on Stackblitz (Based on MUI's provided stackblitz of TextField
) and here is the code :
import * as React from 'react';
import Box from '@mui/material/Box';
import TextField from '@mui/material/TextField';
import * as _ from 'lodash';
export default function BasicTextFields() {
const inputRefs = React.useRef([]);
React.useEffect(() => {
console.log(inputRefs.current);
});
return (
<Box
component="form"
sx={{
'& > :not(style)': { m: 1, width: '25ch' },
}}
noValidate
autoComplete="off"
>
{_.times(6, (i) => (
<TextField
key={Math.random()}
inputRef={(el) => (inputRefs.current[i] = el)}
defaultValue={`input number ${i}`}
id="outlined-basic"
label="Outlined"
variant="outlined"
/>
))}
</Box>
);
}
You can see in the console that an array of refs is displayed.