I am making 2 otp input in my application.
In Input.tsx
, I am using react-otp-input
for the otp functionality
if
<OtpInput
value={"abcde"}
...
numInputs={5}
/>
The UI of react-otp-input
will be
Now the problem is, when I try to change the value of otp, it throws error
Cannot set properties of undefined (setting 'value')
How can I fix it?
Input.tsx
import React, { useState } from "react";
import OtpInput from "react-otp-input";
type InputPropType = {
value: string;
setValue: (event: string) => void;
};
function Input(props: InputPropType): JSX.Element {
const { value, setValue } = props;
return (
<OtpInput
value={value}
onChange={(e: string) => {
setValue(e);
}}
numInputs={5}
/>
);
}
export default Input;
App.tsx
import React, { useState } from "react";
import Input from "./Input";
export default function App() {
type InputValueType = {
id: number;
value: string;
};
const [inputValues, setInputValues] = useState<Array<InputValueType>>([
{ id: 0, value: "" },
{ id: 1, value: "" }
]);
const InputGroup = () => {
let numOfInputs: number = 2;
var rows: Array<any> = [];
for (var i = 0; i < numOfInputs; i++) {
let inputValue: InputValueType = inputValues[i];
rows.push(
<Input
key={inputValue.id}
value={inputValue.value}
setValue={(event: string) => {
let inputValuesTemp = inputValues;
inputValuesTemp[i]["value"] = event;
setInputValues(inputValuesTemp);
}}
/>
);
}
return <>{rows}</>;
};
return (
<div className="App">
<InputGroup />
</div>
);
}
Codesandbox
https://codesandbox.io/s/react-typescript-forked-s38ck9?file=/src/App.tsx:0-918
Few things to be corrected,
var
instead of let
. All the i
variables refer to the same for-loop closure in the for-loop, which means i
is 2
at the end of the iteration.
All the inputValuesTemp[i]
are now resolved to inputValuesTemp[2]
which is definitely undefined
.Replace var
with let
to create closures for each iteration of the loop.
for (let i = 0; i < numOfInputs; i++) {...}
let inputValuesTemp = [...inputValues];
InputGroup
component was within the App
component, which caused you to lose focus for each keystroke. To fix the focus issue, move the InputGroup
out of the App
and keep it as a separate component.import React, { useState } from "react";
import Input from "./Input";
type InputValueType = {
id: number;
value: string;
};
const InputGroup = () => {
const [inputValues, setInputValues] = useState<Array<InputValueType>>([
{ id: 0, value: "" },
{ id: 1, value: "" }
]);
let numOfInputs: number = 2;
var rows: Array<any> = [];
for (let i = 0; i < numOfInputs; i++) {
let inputValue: InputValueType = inputValues[i];
rows.push(
<Input
key={inputValue.id}
value={inputValue.value}
setValue={(event: string) => {
let inputValuesTemp = [...inputValues];
inputValuesTemp[i]["value"] = event;
setInputValues(inputValuesTemp);
}}
/>
);
}
return <>{rows}</>;
};
export default function App() {
return (
<div className="App">
<InputGroup />
</div>
);
}