Issue
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
Solution
Few things to be corrected,
- There is an issue with closures in your for-loop since you have used
var
instead oflet
. All thei
variables refer to the same for-loop closure in the for-loop, which meansi
is2
at the end of the iteration. All theinputValuesTemp[i]
are now resolved toinputValuesTemp[2]
which is definitelyundefined
.
Replace var
with let
to create closures for each iteration of the loop.
for (let i = 0; i < numOfInputs; i++) {...}
- And, you also need o get a copy of the values array for react to do a rerender (to inform that the array has changed).
let inputValuesTemp = [...inputValues];
- Your
InputGroup
component was within theApp
component, which caused you to lose focus for each keystroke. To fix the focus issue, move theInputGroup
out of theApp
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>
);
}
Answered By - Amila Senadheera
0 comments:
Post a Comment
Note: Only a member of this blog may post a comment.