unable to update Image (base64) in next js - javascript

Guys I am trying to update the image i.e base64 string data everything works fine even before submitting the data new image is also displayed correctly but when I submit data it won't update the image
here is my code
import React, { useEffect } from 'react'
import Sidebar_com from '../components/Sidebar_com';
import { useState } from 'react'
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.css';
import FileBase from 'react-file-base64'
import { update_Category, getCategoriesData, getCategoryById } from '#/services/admin'
import Router from 'next/router';
import Image from 'next/image';
export async function getStaticProps({ params }) {
const CategoryData = await getCategoryById(params.id);
return {
props: { CategoryData }
}
}
export async function getStaticPaths() {
const category = await getCategoriesData()
return {
paths: category.map(cate => {
return {
params: { id: String(cate._id) }
};
}),
fallback: false
};
}
export default function updateCategory({ CategoryData }) {
const [cateData, setCateData] = useState(CategoryData);
const [imageData, setImageData] = useState(cateData.image || null);
const handleImageChange = (base64) => {
setImageData(base64);
};
const handleInputChange = (e) => {
if (e.target.type === "checkbox") {
setCateData({ ...cateData, [e.target.name]: e.target.checked });
} else {
setCateData({ ...cateData, [e.target.name]: e.target.value });
}
};
const updateNow = async () =>
{
const res = await update_Category(cateData)
if (res.msg) {
toast.success(res.msg);
Router.push('/admin/categories');
}
else {
toast.error(res.error);
}
}
const handleSubmit = async (e) => {
e.preventDefault();
setCateData({...cateData , image : imageData}, updateNow())
}
return (
<div className='w-full h-screen bg-slate-900 flex'>
<Sidebar_com />
<div className='w-10/12 h-full text-white flex flex-col items-center overflow-auto'>
<div className='w-full p-4 mt-10 mb-4 flex items-center justify-center'>
<h1 className='text-4xl font-semibold tracking-widest border-b p-2 uppercase'>Add Category</h1>
</div>
<form className='text-white' onSubmit={handleSubmit}>
<div class="mb-6">
<label for="email" class="block mb-2 text-sm font-medium text-white dark:text-white">Category Name</label>
<input name='name' value={cateData.name} onChange={handleInputChange} type="text" id="email" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-orange-600 focus:border-orange-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-orange-500 dark:focus:border-orange-500" placeholder="Category name" required />
</div>
<div class="mb-6">
<label for="password" class="block mb-2 text-sm font-medium text-white dark:text-white">Category Slug</label>
<input name='slug' value={cateData.slug} onChange={handleInputChange} type="text" id="password" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-orange-500 focus:border-orange-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-orange-500 dark:focus:border-orange-500" required placeholder='Slug' />
</div>
<div class="flex items-start mb-6">
<div class="flex items-center h-5">
<input name='featured' onChange={handleInputChange} checked={cateData.featured} id="remember" type="checkbox" class="w-4 h-4 border border-gray-300 rounded bg-gray-50 focus:ring-3 focus:ring-orange-300 dark:bg-gray-700 dark:border-gray-600 dark:focus:ring-orange-600 dark:ring-offset-gray-800 dark:focus:ring-offset-gray-800" />
</div>
<label for="remember" class="ml-2 text-sm font-medium text-white dark:text-gray-300">Featured Product</label>
</div>
<div class="mb-6">
<label for="message" class="block mb-2 text-sm font-medium text-gray-900 dark:text-white">Description</label>
<textarea name='description' value={cateData.description} onChange={handleInputChange} id="message" rows="4" class="block p-2.5 w-full text-sm text-gray-900 bg-gray-50 rounded-lg border border-gray-300 focus:ring-orange-500 focus:border-orange-500 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-orange-500 dark:focus:border-orange-500" placeholder="Leave a comment..."></textarea>
</div>
{cateData.image &&
<div>
<Image width={300} height={200} src={cateData.image} alt="no image" />
</div>
}
<div class="mb-6">
<label for="password" class="block mb-2 text-sm font-medium text-white dark:text-white">Category Image</label>
<FileBase onDone={({ base64 }) => handleImageChange(base64)} type="text" id="password" class="bg-gray-50 border border-gray-300 text-gray-900 text-sm rounded-lg focus:ring-orange-500 focus:border-orange-500 block w-full p-2.5 dark:bg-gray-700 dark:border-gray-600 dark:placeholder-gray-400 dark:text-white dark:focus:ring-orange-500 dark:focus:border-orange-500" required placeholder='Slug' />
</div>
<button type="submit" class="text-white bg-orange-600 hover:bg-orange-600 focus:ring-4 focus:outline-none focus:ring-orange-600 font-medium rounded-lg text-sm w-full sm:w-auto px-5 py-2.5 text-center dark:bg-orange-600 dark:hover:bg-orange-600 dark:focus:ring-orange-600">Submit</button>
</form>
</div>
<ToastContainer />
</div>
)
}[enter image description here][1]
look at this I change the image as well as name of category , name changed perfectly but image remain old
is there any way to fix this issue

I think you have a typo in your handleSubmit. It should be:
const handleSubmit = async (e) => {
e.preventDefault();
setCateData({...cateData , image : imageData});
updateNow();
}
BUT, you are using cateData state in your updateNow function which will not be up to date so you better pass the data as parameter.

Related

React loader spinner is not showing on Route

When a user registers it should show the spinner and send them to the dashboard page. I have it set to 8 seconds to allow plenty of time for backend but it still doesn't show. Below is the code.I have state set and using a useeffect setting a timeout and a ternary operator to navigate to the dashboard in the jsx
const CREATE_USER = gql`
mutation CreateUser($userInput: UserInput!, $profileInput: ProfileInput) {
createUser(userInput: $userInput, profileInput: $profileInput) {
token
userId
tokenExpiration
}
}
`;
const Register = (props) => {
let navigate = useNavigate();
const [isLoading, setIsLoading] = useState(true);
useEffect(() => {
setIsLoading(false);
setTimeout(() => {}, 8000);
},[]);
//dont need context yet
const context = useContext(AuthContext);
const [errors, setErrors] = useState([]);
function loginUserCallback() {
login();
}
//1. record values from input here
//2. send it in empty, and hook returns with k/v pairs
const { onChange, onSubmit, values } = useForm(loginUserCallback, {
email: "",
password: "",
firstName: "",
lastName: "",
dob: "",
city: "",
state: "",
bio: "",
occupation: "",
});
//3. separate values
//replace with values.email... etc
const userInput = {
email: values.email,
password: values.password,
firstName: values.firstName,
lastName: values.lastName,
dob: values.dob,
city: values.city,
state: values.state,
};
const profileInput = {
bio: values.bio,
occupation: values.occupation,
};
const [login, { loading }] = useMutation(CREATE_USER, {
update(proxy, { data: { createUser: userData } }) {
context.login(userData);
navigate("/dashboard");
},
onError({ graphQLErrors }) {
setErrors(graphQLErrors);
},
//4. send as variables to backend
variables: {
userInput: userInput,
profileInput: profileInput,
},
});
if (loading) {
<h1>error loading</h1>;
}
return (
<>
{isLoading ? <Loading /> : <Dashboard />}
<img
src="https://floatui.com/logo.svg"
width={150}
className="mx-auto"
alt="logo"
/>
<div className="text-center font-semibold font-serif mt-4">REGISTER</div>
<form onSubmit={onSubmit}>
<div className="max-w-md px-4 mx-auto mt-12">
<label htmlFor="email" className="block py-2 text-gray-500">
Email
</label>
<input
name="email"
type="text"
placeholder="email"
id="email"
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:border-indigo-600 shadow-sm rounded-lg"
required
onChange={onChange}
/>
</div>
<div className="max-w-md px-4 mx-auto mt-12">
<label htmlFor="password" className="block py-2 text-gray-500">
Password
</label>
<input
name="password"
type="text"
placeholder="password"
id="password"
className="w-full mt-2 px-3 py-2 bg-transparent outline-none border focus:border-indigo-600 shadow-sm rounded-lg"
onChange={onChange}
required
/>
</div>
<div className="max-w-md px-4 mx-auto mt-12">
<label htmlFor="firstName" className="block py-2 text-gray-500">
First Name
</label>
<input
name="firstName"
type="text"
placeholder="firstName"
id="firstName"
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:border-indigo-600 shadow-sm rounded-lg"
onChange={onChange}
required
/>
</div>
<div className="max-w-md px-4 mx-auto mt-12">
<label htmlFor="lastName" className="block py-2 text-gray-500">
lastName
</label>
<input
type="text"
name="lastName"
placeholder="lastName"
id="lastName"
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:border-indigo-600 shadow-sm rounded-lg"
onChange={onChange}
required
/>
</div>
<div className="max-w-md px-4 mx-auto mt-12">
<label htmlFor="Date of Birth" className="block py-2 text-gray-500">
Date of Birth
</label>
<input
name="dob"
type="date"
placeholder="dob"
id="dob"
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:border-indigo-600 shadow-sm rounded-lg"
onChange={onChange}
required
/>
</div>
<div className="max-w-md px-4 mx-auto mt-12">
<label htmlFor="city" className="block py-2 text-gray-500">
City
</label>
<input
name="city"
type="text"
placeholder="city"
id="city"
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:border-indigo-600 shadow-sm rounded-lg"
onChange={onChange}
required
/>
</div>
<div className="max-w-md px-4 mx-auto mt-12">
<label htmlFor="state" className="block py-2 text-gray-500">
State
</label>
<input
name="state"
type="text"
placeholder="state"
id="state"
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:border-indigo-600 shadow-sm rounded-lg"
onChange={onChange}
required
/>
</div>
<div className="max-w-md px-4 mx-auto mt-12">
<label htmlFor="occupation" className="block py-2 text-gray-500">
Occupation
</label>
<input
name="occupation"
type="text"
placeholder="occupation"
id="occupation"
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:border-indigo-600 shadow-sm rounded-lg"
onChange={onChange}
required
/>
</div>
<div className="max-w-md px-4 mx-auto mt-12">
<label htmlFor="state" className="block py-2 text-gray-500">
Bio
</label>
<textarea
name="bio"
type="text"
placeholder="bio"
id="state"
rows="4"
col="50"
className="w-full mt-2 px-3 py-2 text-gray-500 bg-transparent outline-none border focus:border-indigo-600 shadow-sm rounded-lg"
onChange={onChange}
required
/>
</div>
<div className="flex justify-center">
<button className="mt-5 px-6 py-2 text-white duration-150 bg-indigo-600 rounded-lg hover:bg-indigo-700 active:shadow-lg">
REGISTER
</button>
</div>
</form>
</>
);
};
export default Register;
The reason why the spinner is not showing up is because the loadingvariable from usemutation is not correctly handled.
In the code, the loading variable is destructured from the useMutation hook as follows:
const [login, { loading }] = useMutation(CREATE_USER, {...})
However, when you check if loadingistrue in the return statement, you do not return any component or text. Instead, you just have a comment. Therefore, even though the loading variable may be true, no spinner is actually displayed.
To fix this, you should return a loading spinner, such as:
if (loading) {
return <Loading />;
}
This will cause the Loading component to be displayed while the mutation is being processed.
Additionally, in the useEffect hook, you are not actually doing anything after the 8-second timeout. To display the spinner for 8 seconds, you should update the useEffect hook as follows:
useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 8000);
}, []);
This will change the value of isLoading to false after 8 seconds, causing the Dashboard component to be displayed.
Overall, your Register component should look something like this:
const Register = (props) => {
const navigate = useNavigate();
const [isLoading, setIsLoading] = useState(true);
const context = useContext(AuthContext);
const [errors, setErrors] = useState([]);
useEffect(() => {
setTimeout(() => {
setIsLoading(false);
}, 8000);
}, []);
const { onChange, onSubmit, values } = useForm(loginUserCallback, {
email: "",
password: "",
firstName: "",
lastName: "",
dob: "",
city: "",
state: "",
bio: "",
occupation: "",
});
const userInput = {
email: values.email,
password: values.password,
firstName: values.firstName,
lastName: values.lastName,
dob: values.dob,
city: values.city,
state: values.state,
};
const profileInput = {
bio: values.bio,
occupation: values.occupation,
};
const [login, { loading }] = useMutation(CREATE_USER, {
update(proxy, { data: { createUser: userData } }) {
context.login(userData);
navigate("/dashboard");
},
onError({ graphQLErrors }) {
setErrors(graphQLErrors);
},
variables: {
userInput: userInput,
profileInput: profileInput,
},
});
if (loading) {
return <Loading />;
}
return (
<>
{isLoading ? <Loading /> : <Dashboard />}
<img
src="https://floatui.com/logo.svg"
width={150}
className="mx-auto"
alt="logo"
/>
<div className="text-center font-semibold font-serif mt-4">REGISTER</div>
<form onSubmit={onSubmit}>
...
</form>
</>
);
};

Next.js: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined

I'm new to Next.js and I have encountered an error as below:
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of `Formik`.
my Login component
export const Login = () => {
const { LoginUser, isFetching, loginError } = useContext(UserContext)
console.log(loginError)
return (
<>
<Formik
validationSchema={LoginValidationSchema}
initialValues={{
email: "",
password: "",
}}
onSubmit={(values) => {
LoginUser(values);
console.log(values)
}}
>
{() => (
<>
<div className='w-full relative h-screen max-h-screen'>
<div className='absolute py-2'>
<Link href="/" className="text-3xl font-bold py-2">title</Link>
</div>
<Form className='w-full h-full flex flex-col justify-center items-center'>
<div className='flex flex-col bg-gray-200 mx-1 xsm:px-10 px-5 py-5 w-auto xsm:w-[350px] rounded'>
<div className='border-b-[2px] border-gray-400 py-2'>
<h1 className='font-semibold text-3xl'>Welcome back</h1>
<h1 className='font-light text-xl'>Login</h1>
</div>
<div className='flex flex-col'>
<div className='flex mt-2 flex-col'>
<label className='font-semibold' htmlFor="email">Email</label>
<Field type="email" className="px-3 outline-none focus:ring-2 ring-offset-2 ring-offset-gray-200 ring-btnColor font-semibold rounded py-2 bg-white" name="email" id="email" placeholder="Email" />
<ErrorMessage component="p" className='text-red-600 font-semibold' name="email" />
</div>
<div className='flex mt-2 flex-col'>
<label className='font-semibold' htmlFor="password">Password</label>
<Field type="password" className="px-3 outline-none focus:ring-2 ring-offset-2 ring-offset-gray-200 ring-btnColor font-semibold rounded py-2 bg-white" name="password" id="password" placeholder="Password" />
<ErrorMessage component="p" className='text-red-600 font-semibold' name="password" />
</div>
<Link href="/login/forgot_password" className='px-1 py-2 font-medium hover:underline hover:text-btnColor w-fit' >Forgot password</Link>
<button type='submit' disabled={isFetching} className="font-semibold select-none mt-4 text-white rounded px-2 py-2 bg-btnColor disabled:opacity-40 disabled:cursor-not-allowed">{isFetching ? "Submitting" : "Submit"}</button>
</div>
<p className='font-semibold mt-3'>If you don't have an account <Link href="auth/signup" className='text-btnColor hover:text-indigo-500'>signup</Link></p>
</div>
</Form>
</div>
</>
)}
</Formik>
</>
)
}
I don't understand what the error message is implying, I am exporting the login component by default, and I have no other exports, when I remove the formik component and use the normal form and input's the last part of the error becomes Check the render method of `Login` instead of Check the render method of `Formik`

Why can't React display the content?

I have changes react-router-dom where other pages can display the content correctly.
However, I cannot see the content on this page even I change the return elements simply to login page
Could anyone tell me what is wrong with it? thank you very much!!
import { Link } from 'react-router-dom'
import * as ROUTES from '../constants/routes.js'
import FirebaseContext from '../context/firebase'
import { getAuth, signInWithEmailAndPassword } from "firebase/auth";
export default function Login() {
React.useEffect(() => {
document.title= "Login - Instagram"
}, [])
const [email, setEmail] = React.useState("")
const [error, setError] = React.useState("")
const [pwd, setPwd] = React.useState("")
const { firebase } = React.useContext(FirebaseContext)
const [values, setValues] = React.useState({
username: "",
password: ""
})
const isInvalid = values.username === "" || values.password === ""
const handleSubmit = async (e) => {
e.preventdefault()
const auth = getAuth();
signInWithEmailAndPassword(auth, email, pwd)
.then((userCredential) => {
// Signed in
const user = userCredential.user;
console.log(user)
})
.catch((error) => {
setEmail('');
setPwd('');
setError(error.message);
});
}
console.log(error)
console.log(firebase)
const handleChange = e => {
setValues({
...values,
[e.target.name]: e.target.value
})
}
return (
<div className="container flex mx-auto max-w-screen-md items-center h-screen">
<div className="flex w-3/5">
<img src="/images/iphone-with-profile.jpg" alt="iPhone with Instagram app" />
</div>
<div className="flex flex-col w-2/5">
<div className="w-full max-w-xs">
<form onSubmit={handleSubmit} method="POST" className="bg-white shadow-md rounded px-8 pt-6 pb-8 mb-4">
<h1 className="flex justify-center w-full">
<img src="/public/logo.png" alt="Instagram" className="mt-2 w-6/12 mb-4" />
</h1>
<input
id="username"
type="text"
name="username"
placeholder="Email address"
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"
value={values.username}
onChange={handleChange}
/>
<br />
<br />
<input
className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 mb-3 leading-tight focus:outline-none focus:shadow-outline"
id="password"
type="password"
placeholder="Password"
name="password"
value={values.password}
onChange={handleChange}
/>
<br />
<button
className={`bg-blue-600 hover:bg-blue-700 text-white font-bold py-2 px-4 rounded w-full focus:outline-none focus:shadow-outline ${isInvalid && 'cursor-not-allowed opacity-50'}`}
type="button"
>
Sign In
</button>
</form>
</div>
<div className="flex justify-center items-center flex-col w-full bg-white p-4 border">
<p className="text-sm">Don't have an account?{` `}
<Link to={ROUTES.SIGN_UP} className="font-bold">
Sign up
</Link>
</p>
</div>
</div>
</div>
)
}```

How can I get localStorage to work with ReactJS?

I'm working on an MERN based web application and I'm having issues getting ReactJS to save a user token into local storage. It correctly sends data to MongoDB and gets the token back from the React UI but isn't saving the token.
This is the form: (I'm also using tailwind for styling)
<form onSubmit={this.submitInfo} className="shadow-md rounded px-8 pt-6 pb-8 mb-4">
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2">
Username:
<input id="username" type="text" value={this.state.name} onChange={this.inputChange} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"/>
</label>
</div>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2">
Email:
<input id="email" className="shadow" type="email" value={this.state.email} onChange={this.inputChange} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"/>
</label>
</div>
<div className="mb-4">
<label className="block text-gray-700 text-sm font-bold mb-2">
Password:
<input id="password" type="password" value={this.state.password} onChange={this.inputChange} className="shadow appearance-none border rounded w-full py-2 px-3 text-gray-700 leading-tight focus:outline-none focus:shadow-outline"/>
</label>
</div>
<div className="flex items-center justify-between">
<input className="bg-primary hover:bg-highlight text-white font-bold py-2 px-4 rounded focus:outline-none focus:shadow-outline" type="submit" value="Signup"/>
</div>
</form>
This is the function that runs when the submit button is clicked:
submitInfo(event){
fetch(`http://localhost:5000/users/register`, {
method: 'POST',
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify({"userName":this.state.name, "email":this.state.email, "password":this.state.password})
})
.then(response => localStorage.setItem("token", JSON.stringify(response)))
.catch(err => console.error(err));
window.location.href = "/browse"
}
I cant see anything inherently wrong about my implementation. I've tested the API with postman and it sends back a token perfectly fine so the issue must be on the react side. Is there something I'm overlooking?
EDIT:
I tried removing the window redirect and its still unable to save the token.
In addition to what the comments are saying about the redirect and preventDefault, you also need to first extract the JSON object out of the response object before saving it into localStorage. You can do all of that with the following:
submitInfo(event) {
event.preventDefault();
fetch(`http://localhost:5000/users/register`, {
method: 'POST',
headers: {
'Content-type': 'application/json',
},
body: JSON.stringify({"userName":this.state.name, "email":this.state.email, "password":this.state.password})
})
.then(response => response.json())
.then(data => {
localStorage.setItem("token", JSON.stringify(data));
window.location.href = "/browse";
)
.catch(err => console.error(err));
}
You can read more about using the fetch API on the MDN docs here: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

How do I store 5 variable input values in one variable in js? [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 1 year ago.
Improve this question
I have 5 different inputs for taking OTP. and I am using 6 useState hook to get their value.
Now I want to store those 5 input value in the 6th variable I'm passing to my redux store.
I tried this way but it returns an object and also use parseInt but it doesn't work.
const [otp, setOtp] = useState(null);
const [digitOne, setDigitOne] = useState(null);
const [digitTwo, setDigitTwo] = useState(null);
const [digitThree, setDigitThree] = useState(null);
const [digitFour, setDigitFour] = useState(null);
const [digitFive, setDigitFive] = useState(null);
const handleSubmit = (e) => {
e.preventDefault();
const otp = { digitOne, digitTwo, digitThree, digitFour, digitFive };
console.log(digitOne, digitTwo, digitThree, digitFour, digitFive);
dispatch(checkVerification({ user_info, otp })).then(() => {
console.log(otp);
});
};
return (
<form
onSubmit={handleSubmit}
className="flex flex-col justify-start w-full mt-lg "
>
<div className="flex flex-row justify-between mx-auto max-w-screen-xs space-x-2">
<input
type="text"
className="text-xl w-10 text-center bg-transparent border-t-0 border-l-0 border-r-0 focus:ring-0 focus:border-gray-400 border-b border-gray-400 h-10 "
pattern="[0-9]"
maxLength={1}
value={digitOne}
onChange={(e) => setDigitOne(e.target.value)}
/>
<input
type="text"
className="text-xl w-10 text-center bg-transparent border-t-0 border-l-0 border-r-0 focus:ring-0 focus:border-gray-400 border-b border-gray-400 h-10 "
pattern="[0-9]"
maxLength={1}
value={digitTwo}
onChange={(e) => setDigitTwo(e.target.value)}
/>
<input
type="text"
className="text-xl w-10 text-center bg-transparent border-t-0 border-l-0 border-r-0 focus:ring-0 focus:border-gray-400 border-b border-gray-400 h-10 "
pattern="[0-9]"
maxLength={1}
value={digitThree}
onChange={(e) => setDigitThree(e.target.value)}
/>
<input
type="text"
className="text-xl w-10 text-center bg-transparent border-t-0 border-l-0 border-r-0 focus:ring-0 focus:border-gray-400 border-b border-gray-400 h-10 "
pattern="[0-9]"
maxLength={1}
value={digitFour}
onChange={(e) => setDigitFour(e.target.value)}
/>
<input
type="text"
className="text-xl w-10 text-center bg-transparent border-t-0 border-l-0 border-r-0 focus:ring-0 focus:border-gray-400 border-b border-gray-400 h-10 "
pattern="[0-9]"
maxLength={1}
value={digitFive}
onChange={(e) => setDigitFive(e.target.value)}
/>
</div>
<button className="uppercase flex-grow mt-6 p-2 bg-red-500 text-white px-4 rounded mx-lg">
proceed
</button>
</form>
);
Actions
import ApiInstance from "../../Api/root";
import store from "../store";
import { CHECK_VERIFIED } from "../Types/CustomerVerificationTypes";
import {
CUSTOMER_LOGIN_SUCCESS,
GET_CUSTOMER_LOGIN,
} from "../Types/CustomerLoginTypes";
export const checkVerification =
({ user_info, otp }) =>
async (dispatch, getState) => {
const deviceId = getState().device.device.data.device.id;
localStorage.setItem("id", deviceId);
console.log(otp);
const res = await ApiInstance.get(
`customers/otp/verification?mobile_number=${user_info.mobile_number}&country_code=${user_info.country_code}&otp=${otp}&device_id=${deviceId}`,
{
method: "GET",
headers: {
"Content-Type": "application/json",
Accept: "application/json",
},
}
)
.then((res) => {
console.log("Auth Token", res.data);
dispatch({
type: CHECK_VERIFIED,
payload: res.data,
});
// todo only if API Call is success
if (res.data.success) {
localStorage.setItem("authToken", res.data.token);
} else {
alert("Entered OTP is wrong, Try Again");
}
})
.catch((error) => {
console.error(error);
});
};
Also I've set maxLength of input to 1 but How do I move one input to another after user puts a number?
Add The Following Code To Move A The Curosor To Next Input After Adding A Input. Please Validate Cause it will take some time to reproduce and test the answer. anywas you can do this by using the .focus() function on the element.:
const [otp, setOtp] = useState(null);
const [digitOne, setDigitOne] = useState(null);
const [digitTwo, setDigitTwo] = useState(null);
const [digitThree, setDigitThree] = useState(null);
const [digitFour, setDigitFour] = useState(null);
const [digitFive, setDigitFive] = useState(null);
const handleSubmit = (e) => {
e.preventDefault();
const otp = { digitOne, digitTwo, digitThree, digitFour, digitFive };
console.log(digitOne, digitTwo, digitThree, digitFour, digitFive);
dispatch(checkVerification({ user_info, otp })).then(() => {
console.log(otp);
});
};
return (
<form
onSubmit={handleSubmit}
className="flex flex-col justify-start w-full mt-lg "
>
<div className="flex flex-row justify-between mx-auto max-w-screen-xs space-x-2">
<input
type="text"
className="text-xl w-10 text-center bg-transparent border-t-0 border-l-0 border-r-0 focus:ring-0 focus:border-gray-400 border-b border-gray-400 h-10 "
pattern="[0-9]"
maxLength={1}
value={digitOne}
onChange={(e) => {
setDigitOne(e.target.value)
document.getElementById('digitTwo').focus()
}}
id="digOne"
/>
<input
type="text"
className="text-xl w-10 text-center bg-transparent border-t-0 border-l-0 border-r-0 focus:ring-0 focus:border-gray-400 border-b border-gray-400 h-10 "
pattern="[0-9]"
maxLength={1}
value={digitTwo}
id="digitTwo"
onChange={(e) => {
setDigitTwo(e.target.value)
document.getElementById('digitThree').focus()
}}
/>
<input
type="text"
className="text-xl w-10 text-center bg-transparent border-t-0 border-l-0 border-r-0 focus:ring-0 focus:border-gray-400 border-b border-gray-400 h-10 "
pattern="[0-9]"
maxLength={1}
value={digitThree}
id="digitThree"
onChange={(e) => {
setDigitThree(e.target.value)
document.getElementById('digitFour').focus()
}}
enter code here
/>
<input
type="text"
className="text-xl w-10 text-center bg-transparent border-t-0 border-l-0 border-r-0 focus:ring-0 focus:border-gray-400 border-b border-gray-400 h-10 "
pattern="[0-9]"
maxLength={1}
value={digitFour}
id="digitFour"
onChange={(e) => {
setDigitFour(e.target.value)
document.getElementById('digitFive').focus()
}}
enter code here
/>
<input
type="text"
className="text-xl w-10 text-center bg-transparent border-t-0 border-l-0 border-r-0 focus:ring-0 focus:border-gray-400 border-b border-gray-400 h-10 "
pattern="[0-9]"
maxLength={1}
value={digitFive}
id="digitFive"
onChange={(e) => {
setDigitFIve(e.target.value)
}}
/>
</div>
<button className="uppercase flex-grow mt-6 p-2 bg-red-500 text-white px-4 rounded mx-lg">
proceed
</button>
</form>
);
Please Mark It As Correct If It Works!
Kamestart

Categories

Resources