React values not updating through when rendering to child component - reactjs

Please i need help
i am a beginer using react
I find it difficult get values and i just hope my explanation is clear
What will i do or which other approch is best for this
i want to get value={} from main <Controller> and pass it through render={} to be used in the child component <PhoneInput> the value={phone}
is an object that consist of arrays
this is the content of phone
[
{
country: 'bs',
phoneNumber: '122 234 4309',
label: 'Mobile',
},
{
country: 'bs',
phoneNumber: '898 776 9087',
label: 'Work',
},
];
the best of my knowledge is what i did but not it working
My aim is to enable user to add more phone number field by their self
i want a user to be able to delete field or add more phone field
Sample Image
<Controller
control={control}
name="phones"
value={phones} //phone is an array
render={({ field: { onChange, className, value, ref } }) => ( // Transfering value from value={phones} to use as value.map not working
<div className={clsx('mt-32', className)} ref={ref}>
{value.map((item, index) => ( //the value here becomes undefined
<PhoneInput
value={item}
key={index}
onChange={(val) => {
console.log(value);
onChange(value.map((_item, _index) => (index === _index ? val : _item)));
}}
onRemove={() => {
console.log(value);
onChange(value.filter((_item, _index) => index !== _index));
}}
hideRemove={value.length === 1}
/>
))}
<Button
className="group inline-flex items-center mt-2 -ml-4 py-2 px-4 rounded cursor-pointer"
onClick={() =>
onChange([...testPhone, Model().phoneNumbers[0]])
}
>
<span className="ml-8 font-medium text-secondary group-hover:underline">
Add a phone number
</span>
</Button>
</div>
)}
/>
if i send the value directly it works fine
<Controller
control={control}
name="phones"
value={phones}
render={({ field: { onChange, className, value, ref } }) => (
// <div className={clsx('mt-32', className)} ref={ref}>
{phones.map((item, index) => ( //Using variable phone directly
<PhoneInput
value={item}
key={index}
onChange={(val) => {
console.log(phones);
onChange(phones.map((_item, _index) => (index === _index ? val : _item)));
}}
onRemove={() => {
console.log(phones);
onChange(phones.filter((_item, _index) => index !== _index));
}}
hideRemove={phones.length === 1}
/>
))}
<Button
className="group inline-flex items-center mt-2 -ml-4 py-2 px-4 rounded cursor-pointer"
onClick={() =>
onChange([...phones, Model().phoneNumbers[0]])
}
>
<span className="ml-8 font-medium text-secondary group-hover:underline">
Add a phone number
</span>
</Button>
</div>
)}
/>
Here is the complete code
import { motion } from 'framer-motion';
import { useEffect, useState } from 'react';
import {
Button,
Card,
} from '#mui/material';
import clsx from 'clsx';
import { Controller, useForm } from 'react-hook-form';
import axios from 'axios';
import PhoneInput from '../../PhoneInput';
import Model from '../../Model';
/**
* Form Validation Schema
*/
const schema = yup.object().shape({
phone: yup.string().required('Phone is required'),
});
function Settings() {
const { control, watch, reset, handleSubmit, formState, getValues } = useForm({
mode: 'onChange',
resolver: yupResolver(schema),
});
const [phones, setPhones] = useState([]);
useEffect(() => {
axios.get('/api/v1/account').then((res) => {
if (res.data.success === true) {
setPhones(res.data.phones);
}
});
}, []);
return (
<Card
component={motion.div}
variants={IT}
className="w-full overflow-hidden w-full mb-32"
>
<div className=" p-24 w-full">
<Controller
control={control}
name="first_name"
render={({ field }) => (
<TextField
className="mt-32"
{...field}
label="First Name"
placeholder="First Name"
id="first_name"
error={!!errors.first_name}
helperText={errors?.first_name?.message}
variant="outlined"
required
fullWidth
/>
)}
/>
<Controller
control={control}
name="phones"
value={phones}
render={({ field: { onChange, className, value, ref } }) => (
<div className={clsx('mt-32', className)} ref={ref}>
{phones.map((item, index) => (
<PhoneInput
value={item}
key={index}
onChange={(val) => {
console.log(phones);
onChange(phones.map((_item, _index) => (index === _index ? val : _item)));
}}
onRemove={() => {
console.log(phones);
onChange(phones.filter((_item, _index) => index !== _index));
}}
hideRemove={phones.length === 1}
/>
))}
<Button
className="group inline-flex items-center mt-2 -ml-4 py-2 px-4 rounded cursor-pointer"
onClick={() =>
onChange([...phones, Model().phoneNumbers[0]])
}
>
<span className="ml-8 font-medium text-secondary group-hover:underline">
Add a phone number
</span>
</Button>
</div>
)}
/>
</div>
</Card>
);
}
export default Settings;
Thank you very much

Related

Why NextJS give me this hydrating error after refreshing the page?

When I refresh my page I got these erorrs :
Text content does not match server-rendered HTML.
Hydration failed because the initial UI does not match what was rendered on the server.
There was an error while hydrating. Because the error happened outside of a Suspense boundary, the entire root will switch to client rendering.
This is my file code :
/* eslint-disable #next/next/no-img-element */
import Header from '#/components/Header'
import blockContent from '#/medium-sanity-copy/schemas/blockContent'
import { PostType, SlugType } from '#/types'
import { Formik, Field, Form, ErrorMessage } from 'formik'
import { FieldProps } from 'formik/dist/Field'
import { GetStaticProps } from 'next'
import Head from 'next/head'
import React from 'react'
import PortableText from 'react-portable-text'
import { client, urlFor } from './../../sanity'
import * as yup from 'yup'
interface PostProps {
post: PostType
}
let schema = yup.object().shape({
name: yup.string().required('Name field is required'),
comment: yup.string().required('Comment field is required'),
email: yup.string().email('Email field must be email type').required('Email field is required'),
})
const Post: React.FC<PostProps> = ({ post }) => {
const initialValues = {
name: '',
email: '',
comment: '',
}
return (
<div className="mb-10">
<Head>
<title>{post.title}</title>
<link rel="icon" href="https://cdn.iconscout.com/icon/free/png-256/medium-47-433328.png" />
</Head>
<Header />
<div className="max-w-3xl mx-auto px-5 md:px-0">
<div className="my-5">
<h1 className="text-3xl font-bold mb-3">{post.title}</h1>
<h2 className="text-xl text-gray-600">{post.description}</h2>
<div className="flex items-center space-x-3 my-3">
<img
className="h-10 w-10 rounded-full drop-shadow-md"
src={urlFor(post.author?.image).url()}
alt="avatar"
/>
<p className="font-extralight text-gray-600">
Blog post by <span className="text-yellow-600">{post.author?.name}</span> - Published
at {new Date(post._createdAt!).toLocaleString()}
</p>
</div>
</div>
<PortableText
projectId={process.env.NEXT_PUBLIC_SANITY_PROJECT_ID}
dataset={process.env.NEXT_PUBLIC_SANITY_DATASET}
content={post.body!}
serializers={{
h1: (props: any) => <h1 className="text-2xl text-bold my-5" {...props} />,
h2: (props: any) => <h2 className="text-xl text-bold my-5" {...props} />,
li: ({ children }: any) => <li className="ml-4 list-disc">{children}</li>,
link: ({ href, children }: any) => (
<a href={href} className="text-blue-500 hover:underline">
{children}
</a>
),
}}
/>
</div>
<hr className="color bg-yellow-600 h-1 max-w-xl mx-auto mt-10 mb-5" />
<Formik
initialValues={initialValues}
onSubmit={(values) => {
alert(`${values.comment}, ${values.email}, ${values.name}`)
}}
validationSchema={schema}>
{() => (
<Form className="max-w-2xl mx-auto p-5">
<span className="text-yellow-600">Enjoyed this article?</span>
<h1 className="text-3xl font-bold">Leave the comment below!</h1>
<hr className="my-2" />
<div className="flex flex-col my-3">
<label htmlFor="name">Name</label>
<Field name="name">
{({ field }: FieldProps) => (
<input
type="text"
{...field}
className="outline-none border py-2 px-3 rounded shadow"
/>
)}
</Field>
</div>
<div className="flex flex-col my-3">
<label htmlFor="email">Email</label>
<Field name="email">
{({ field }: FieldProps) => (
<input
type="text"
{...field}
className="outline-none border py-2 px-3 rounded shadow"
/>
)}
</Field>
</div>
<div className="flex flex-col my-3">
<label htmlFor="comment">Comment</label>
<Field name="comment">
{({ field }: FieldProps) => (
<textarea
{...field}
rows={8}
className="outline-none border resize-none py-2 px-3 rounded shadow"
/>
)}
</Field>
</div>
<div className="flex flex-col space-y-1 text-red-500 items-center">
<ErrorMessage name="name">{(err) => <span>{err}</span>}</ErrorMessage>
<ErrorMessage name="email">{(err) => <span>{err}</span>}</ErrorMessage>
<ErrorMessage name="comment">{(err) => <span>{err}</span>}</ErrorMessage>
</div>
</Form>
)}
</Formik>
</div>
)
}
export default Post
export const getStaticPaths = async () => {
const query = `
*[_type == "post"]{
_id,
slug
}
`
const posts = await client.fetch(query)
const paths = posts.map((post: { _id: string; slug: SlugType }) => ({
params: {
slug: post.slug.current,
},
}))
return { paths, fallback: false }
}
export const getStaticProps: GetStaticProps = async ({ params }) => {
const query = `
*[_type == "post" && slug.current == $slug][0]{
_id,
_createdAt,
description,
slug,
mainImage,
title,
author -> {
name,
image
},
body
}
`
const post = await client.fetch(query, { slug: params?.slug })
return {
props: {
post,
},
revalidate: 60,
}
}
I didn't find out a solution that I can understand and agree with
This is usually caused when you have a <div> or <h1> element inside a <p> elemnt.
You can find what is causing this issue if you check the console

Simple way to upload image in next.js and using Formik

I want to know the way which where the image can be uploaded to my project. First I want to upload one image to internal folder, second, I want to upload multi images to the same folder
this this my code:
import React from 'react'
import { useSession } from 'next-auth/react';
import Router from 'next/router';
import { forwardRef } from 'react';
import { useFormik, Formik } from 'formik';
import * as Yup from 'yup';
import { FiDollarSign } from 'react-icons/fi';
import NavbarPage from '../../components/navBar';
import Footer from '../../components/footer';
const newproduct = () => {
const { data: session, status } = useSession({
required: true,
})
const [token, setToken] = React.useState('')
React.useEffect(() => {
if(status === 'unauthenticated') Router.replace("/auth/login");
}, [status]);
if(status === 'loading'){
return <div className='h-screen w-screen flex justify-center items-center'><Spinner color="#f59e0b" className="h-12" /></div>
}
if(status === 'authenticated'){
return (
<div className=" bg-gray-700">
<div className='bg-white'>
<NavbarPage />
</div>
<div className='p-4 dashboardHeight' style={{minHeight: 'calc(100vh-206px)'}}>
<h1 className='p-6 font-bold text-4xl text-slate-50'>New Product</h1>
<div className='flex justify-center w-full'>
<Formik
initialValues= {{
title: '',
brand: '',
category: '',
price: '',
quantity: '',
mImage: '',
aImages: '',
}}
validationSchema= {validateSchema}
onSubmit={ async(values) => {
console.log(JSON.stringify(values))
// const res = await fetch("http://localhost:3030/product", {
// method: 'POST',
// body: JSON.stringify(values),
// headers: {
// "Content-Type": "application/json",
// "Authorization": `"${session.user.accessToken}"`
// }
// })
// const user = await res.json();
}}
>
{props => (
<form onSubmit={props.handleSubmit} className="w-4/5" method='post' encType='multipart/form-data'>
<Field
dot={true}
error={props.touched?.title && props.errors?.title}
label="Title (Latin)"
name="title"
onChange={props.handleChange}
type="text"
/>
<Field
dot={true}
error={props.touched?.brand && props.errors?.brand}
label="Brand (Latin)"
name="brand"
onChange={props.handleChange}
type="text"
/>
<Field
dot={true}
error={props.touched?.category && props.errors?.category}
label="Category (Latin)"
name="category"
onChange={props.handleChange}
type="select"
>
<option>-Select Product Category-</option>
<option value="Supermarket">Supermarket</option>
<option value="Fashion">Fashion</option>
<option value="Health & Beauty">Health & Beauty</option>
<option value="Baby Products">Baby Products</option>
<option value="Phones & Tablets">Phones & Tablets</option>
<option value="Home & Office">Home & Office</option>
<option value="Electronics">Electronics</option>
<option value="Computing">Computing</option>
<option value="Sporting Goods">Sporting Goods</option>
<option value="Gaming">Gaming</option>
<option value="Automobile">Automobile</option>
</Field>
<Field
dot={true}
error={props.touched?.price && props.errors?.price}
icon={<PriceIcon />}
label="Price"
name="price"
onChange={props.handleChange}
type="text"
/>
<Field
dot={true}
error={props.touched?.quantity && props.errors?.quantity}
label="Quantity"
name="quantity"
onChange={props.handleChange}
type="text"
/>
<Field
dot={true}
error={props.touched?.mImage && props.errors?.mImage}
label="Main Image"
name="mImage"
onChange={props.handleChange}
type="file"
/>
<Field
dot={false}
error={props.touched?.aImages && props.errors?.aImages}
label="Addtional Images"
name="aImages"
onChange={props.handleChange}
type="file"
// multiple="multiple"
/>
<button
className="mt-8 bg-black active:bg-gray-900 focus:outline-none text-white rounded px-4 py-1"
type="submit"
>
Add Product
</button>
</form>)}
</Formik>
</div>
</div>
<Footer/>
</div>
)
}
}
export default newproduct
// Yup validation schema
const validateSchema = Yup.object().shape({
title: Yup.string().required('Field is required'),
brand: Yup.string().required('Field is required'),
category: Yup.string().required('Field is required'),
price: Yup.string().required('Field is required'),
quantity: Yup.string().required('Field is required'),
mImage: Yup.string(),
aImages: Yup.string(),
});
/* COMPONENT LOGIC */
const style = {
dot: `after:content-['*'] after:ml-0.5 after:text-red-500`,
error: `ring-red-500 ring-1`,
disabled: `cursor-not-allowed`,
container: `relative mb-6 mt-3`,
errorMessage: `text-sm text-red-500 mt-2`,
checkboxLabel: `block overflow-hidden h-6 rounded-full bg-gray-300`,
checkboxContainer: `relative w-10 mr-2 align-middle select-none mt-2`,
iconContainer: `absolute flex border border-transparent left-0 top-0 h-full w-10`,
icon: `flex items-center justify-center rounded-tl rounded-bl z-10 text-gray-400 text-lg h-full w-full`,
checkbox: `checked:bg-blue-500 checked:right-0 focus:outline-none right-4 duration-200 ease-in absolute block w-6 h-6 rounded-full bg-white border-4 appearance-none cursor-pointer`,
default: `text-base relative flex flex-1 w-full mt-1 rounded-md py-2 px-4 bg-white text-gray-700 placeholder-gray-400 text-base focus:outline-none focus:ring-1 focus:border-transparent border`,
};
const Field = forwardRef(
(
{ disabled, dot, error, icon, label, name, type = 'text', ...rest },
ref,
) => {
let component;
// if you won't use select, you can delete this part
if (type === 'select') {
component = (
<select
aria-required={dot}
aria-invalid={!!error}
className={`${style.default} ${disabled ? style.disabled : ''}
${error ? style.error : 'border-gray-300'}
`}
disabled={disabled}
id={name}
name={name}
ref={ref}
{...rest}
/>
);
}
// if you won't use textarea, you can delete this part
if (type === 'textarea') {
component = (
<textarea
aria-required={dot}
aria-invalid={!!error}
className={`${style.default} ${disabled ? style.disabled : ''}
${error ? style.error : 'border-gray-300'}
`}
disabled={disabled}
id={name}
name={name}
ref={ref}
{...rest}
/>
);
}
// if you won't use checkbox, you can delete this part and the classes checkbox, checkboxContainer and checkboxLabel
if (type === 'checkbox') {
component = (
<div className={style.checkboxContainer}>
<input
aria-required={dot}
aria-invalid={!!error}
className={`${style.checkbox} ${disabled ? style.disabled : ''}`}
disabled={disabled}
id={name}
name={name}
type="checkbox"
{...rest}
/>
<span className={style.checkboxLabel} />
</div>
);
}
// if you won't use input, you can delete this part
if (type !== 'checkbox' && type !== 'select' && type !== 'textarea') {
component = (
<div className="relative">
<div className={style.iconContainer}>
<div className={style.icon}>{icon}</div>
</div>
<input
aria-required={dot}
aria-invalid={!!error}
className={`${style.default} ${icon ? 'pl-12' : ''}
${error ? style.error : 'border-gray-300'}
${disabled ? style.disabled : ''}
`}
disabled={disabled}
id={name}
name={name}
type={type}
ref={ref}
{...rest}
/>
{error && <ErrorIcon />}
</div>
);
}
return (
<div className={`${style.container} ${disabled ? 'opacity-50' : ''}`}>
<label htmlFor={name} className={`text-white ${dot && style.dot}`}>
{label}
</label>
{component}
{error && (
<span role="alert" className={style.errorMessage}>
{error}
</span>
)}
</div>
);
},
);
Field.displayName = 'Field';
const ErrorIcon = () => (
<svg
xmlns="http://www.w3.org/2000/svg"
width="15"
height="15"
fill="currentColor"
className="absolute right-2 -mt-7 text-red-500"
viewBox="0 0 1792 1792"
>
<path d="M1024 1375v-190q0-14-9.5-23.5t-22.5-9.5h-192q-13 0-22.5 9.5t-9.5 23.5v190q0 14 9.5 23.5t22.5 9.5h192q13 0 22.5-9.5t9.5-23.5zm-2-374l18-459q0-12-10-19-13-11-24-11h-220q-11 0-24 11-10 7-10 21l17 457q0 10 10 16.5t24 6.5h185q14 0 23.5-6.5t10.5-16.5zm-14-934l768 1408q35 63-2 126-17 29-46.5 46t-63.5 17h-1536q-34 0-63.5-17t-46.5-46q-37-63-2-126l768-1408q17-31 47-49t65-18 65 18 47 49z" />
</svg>
);
const LockIcon = () => (
<svg
height="20"
width="20"
stroke="currentColor"
fill="currentColor"
strokeWidth="0"
viewBox="0 0 448 512"
xmlns="http://www.w3.org/2000/svg"
>
<path d="M400 224h-24v-72C376 68.2 307.8 0 224 0S72 68.2 72 152v72H48c-26.5 0-48 21.5-48 48v192c0 26.5 21.5 48 48 48h352c26.5 0 48-21.5 48-48V272c0-26.5-21.5-48-48-48zm-104 0H152v-72c0-39.7 32.3-72 72-72s72 32.3 72 72v72z" />
</svg>
);
const PriceIcon = () => (
<FiDollarSign className="text-3xl"/>
);
const Spinner = ({ color, className }) => (
<svg
fill={color}
viewBox="0 0 1792 1792"
className={`${className} flex-no-shrink animate-spin`}
xmlns="http://www.w3.org/2000/svg"
>
<path d="M1760 896q0 176-68.5 336t-184 275.5-275.5 184-336 68.5-336-68.5-275.5-184-184-275.5-68.5-336q0-213 97-398.5t265-305.5 374-151v228q-221 45-366.5 221t-145.5 406q0 130 51 248.5t136.5 204 204 136.5 248.5 51 248.5-51 204-136.5 136.5-204 51-248.5q0-230-145.5-406t-366.5-221v-228q206 31 374 151t265 305.5 97 398.5z" />
</svg>
);
I tried using FileReader but I didn't get the way and it's hard to handle it with Formik, what is the simplest and best way to implement this
well, you can upload an image to your project using the File input element in your form and handle the file in your form submission handler.
Here is an example of how you can modify your code to achieve this:
Add a File input element to your form:
<input
name="mImage"
type="file"
onChange={(event) => {
// handle the file input change event
}}
/>
then, in your form submission handler, get the file from the event.target.files property of the input element:
onSubmit={(event) => {
event.preventDefault();
const file = event.target.files[0];
// do something with the file, such as uploading it to a server
}}
To upload multiple images, you can use the multiple attribute of the File input element and handle the files in your form submission handler in a similar way.

error - Form submission canceled because the form is not connected React

I´m currently doing a userinformations component with various required textfields (by material ui).
At the bottom the user has the options to go one step back (cancel the submission) or go to the next step (at the end the user will pay for a service).
Component looks like this:
<>
<CustomizeYourAudit />
<form onSubmit={() => setPaymentStep(2)}>
<AuditInfo auditInfo={auditInfo} setAuditInfo={setAuditInfo} />
{/***************** buttons at the bottom of the payment modal ****************/}
<div className="p-4 flex justify-center">
<button
type="button"
className="order-btn-back"
onClick={() => setShowPaymentModal(false)}>
Cancel
</button>
<span className="px-3" />
<button type="submit" className="order-btn-next">
Next
</button>
</div>
</form>
{/***************** buttons at the bottom of the payment modal END ****************/}
</>
In the auditinfo component I have the following code (ignore the react dropzone):
import { useDropzone } from 'react-dropzone';
import { TextField } from '#mui/material/';
import DragAccepted from './DragAccepted';
import DragRejected from './DragRejected';
import DragInactive from './DragInactive';
import ImagePreview from './ImagePreview';
import './imageDropzone.scss';
interface AuditInfoProps {
auditInfo: AuditInfoType;
setAuditInfo: React.Dispatch<React.SetStateAction<AuditInfoType>>;
}
const AuditInfo = ({ auditInfo, setAuditInfo }: AuditInfoProps) => {
const {
isDragActive,
isDragAccept,
isDragReject,
getRootProps,
getInputProps
} = useDropzone({
accept: {
'image/png': ['.png'],
'image/jpeg': ['.jpg', '.jpeg']
},
maxFiles: 1,
multiple: false,
onDrop: (acceptedFiles) => {
setAuditInfo((prevState) => ({
...prevState,
projectLogo: acceptedFiles.map((file) =>
Object.assign(file, {
preview: URL.createObjectURL(file)
})
)
}));
}
});
return (
<div>
{/***************** Imagedropzone ****************/}
<div className="lg:grid lg:grid-cols-3 justify-around border-b-2">
<div className="border-r-2 p-3 m-auto">
<div
{...getRootProps({
className: 'dropzone-upload-wrapper rounded-lg '
})}>
<input {...getInputProps()} />
<div className="dropzone-inner-wrapper dropzone-inner-wrapper-alt rounded-lg p-8">
{isDragAccept && <DragAccepted />}
{isDragReject && <DragRejected />}
{!isDragActive && <DragInactive />}
</div>
</div>
</div>
<div className="lg:col-span-2 m-auto">
{auditInfo.projectLogo != false ? (
<ImagePreview files={auditInfo.projectLogo} />
) : (
<p className="text-center">Image preview will be shown here</p>
)}
</div>
</div>
{/***************** Imagedropzone End ****************/}
{/***************** Project name and title ****************/}
<div className="p-6 rounded">
<TextField
value={auditInfo.projectName}
id="outlined-basic"
type="text"
label="Project Name"
variant="outlined"
required
onChange={(e) =>
setAuditInfo((prevState) => ({
...prevState,
projectName: e.target.value
}))
}
sx={{ marginBottom: '1.5rem' }}
/>
<TextField
value={auditInfo.projectDescription}
fullWidth
type="text"
id="outlined-basic"
label="Project Description"
multiline
rows="6"
variant="outlined"
required
onChange={(e) =>
setAuditInfo((prevState) => ({
...prevState,
projectDescription: e.target.value
}))
}
/>
</div>
{/***************** Project name and title End ****************/}
</div>
);
};
export default AuditInfo;
So the code actually works perfectly fine and I can´t click the submit button, until I have filled in the required fields.
Any idea what could be wrong here?
Cheers!

Material-UI: Upload PDF file

I have a ready-made template and in this template there is a file, which is the file below, and this code is through which you can select several images from the computer as shown in the image, but the problem is that I do not want to choose an image. I want to choose a PDF file and I tried to make Several changes such as changing the type of the selected file from image to file, but my problem was not resolved.
import { orange } from '#material-ui/core/colors';
import Icon from '#material-ui/core/Icon';
import { makeStyles } from '#material-ui/core/styles';
import clsx from 'clsx';
import FuseUtils from '#fuse/utils';
import { Controller, useFormContext } from 'react-hook-form';
function ProductImagesTab(props) {
const classes = useStyles(props);
const methods = useFormContext();
const { control, watch, setValue } = methods;
const images = watch('images');
return (
<div>
<div className="flex justify-center sm:justify-start flex-wrap -mx-16">
<Controller
name="images"
control={control}
render={({ field: { onChange, value } }) => (
<label
htmlFor="button-file"
className={clsx(
classes.productImageUpload,
'flex items-center justify-center relative w-128 h-128 rounded-16 mx-12 mb-24 overflow-hidden cursor-pointer shadow hover:shadow-lg'
)}
>
<input
accept="image/*"
className="hidden"
id="button-file"
type="file"
onChange={async (e) => {
function readFileAsync() {
return new Promise((resolve, reject) => {
const file = e.target.files[0];
if (!file) {
return;
}
const reader = new FileReader();
reader.onload = () => {
resolve({
id: FuseUtils.generateGUID(),
url: `data:${file.type};base64,${btoa(reader.result)}`,
type: 'image',
});
};
reader.onerror = reject;
reader.readAsBinaryString(file);
});
}
const newImage = await readFileAsync();
onChange([newImage, ...value]);
}}
/>
<Icon fontSize="large" color="action">
cloud_upload
</Icon>
</label>
)}
/>
<Controller
name="featuredImageId"
control={control}
defaultValue=""
render={({ field: { onChange, value } }) =>
images.map((media) => (
<div
onClick={() => onChange(media.id)}
onKeyDown={() => onChange(media.id)}
role="button"
tabIndex={0}
className={clsx(
classes.productImageItem,
'flex items-center justify-center relative w-128 h-128 rounded-16 mx-12 mb-24 overflow-hidden cursor-pointer outline-none shadow hover:shadow-lg',
media.id === value && 'featured'
)}
key={media.id}
>
<Icon className={classes.productImageFeaturedStar}>star</Icon>
<img className="max-w-none w-auto h-full" src={media.url} alt="product" />
</div>
))
}
/>
</div>
</div>
);
}
export default ProductImagesTab;
Looks like your Input HTML element is set to accept="image/*"
Instead you should have it accept pdf format like this <input type="file" accept="application/pdf">
https://www.w3schools.com/tags/tag_input.asp
Similar question answered here

How can I display formatted_address from geocode inside my formik form?

I want to display the console.log(formatted_address) from geocode inside my formik form once the user click the use my current location button. Here is code below:
const [address, setAddress] = useState({
address: {
formatted_address: "",
latitude: "",
longitude: ""
}
})
const successPosition = (position) => {
const latitude = position.coords.latitude;
const longitude = position.coords.longitude;
setAddress({ address: { ...address.address, latitude, longitude } })
// set Google Maps Geocoding API for purposes of quota management. Its optional but recommended.
Geocode.setApiKey(API_Key);
// set response language. Defaults to english.
Geocode.setLanguage("en");
// set response region. Its optional.
// A Geocoding request with region=es (Spain) will return the Spanish city.
Geocode.setRegion("ng");
// Enable or disable logs. Its optional.
Geocode.enableDebug();
// Get address from latitude & longitude.
Geocode.fromLatLng(latitude, longitude).then(
(response) => {
const formatted_address = response.results[0].formatted_address;
setAddress({
address: { ...address.address, formatted_address }
});
console.log(formatted_address)
},
(error) => {
console.error(error);
}
);
}
const getCurrentLocation = () => {
if ("geolocation" in navigator) {
navigator.geolocation.getCurrentPosition(
(pos) => successPosition(pos),
);
} else {
alert("Your Browser doesn't support location service !");
}
};
And display that formatted_address inside the formik form below in order to fill it once the users decide to use the use my current location button to fill the form. when I insert {address.formatted_address} it's saying it's not defined. I set it as the value inside the address input.
<Formik
initialValues={{
address: '',
city: '',
state: '',
country: '',
}}
onSubmit={(values, actions) => {
setTimeout(() => {
alert(JSON.stringify(values, null, 2))
actions.setSubmitting(false)
}, 1000)
}}
>
{({ values, handleSubmit, handleChange, handleBlur }) => (
<Form
onSubmit={handleSubmit}
autoComplete='off'
className='text-left lg:w-full lg:py-10 lg:px-0 md:py-5 sm:py-10'
>
<div className=''>
<label htmlFor='address' className='font-semibold'>
Address
</label>
<input
type='address'
name='address'
placeholder='Enter your address'
onChange={handleChange}
onBlur={handleBlur}
value={address.formatted_address}
className='border-2 border-[#F6F6F6]
rounded w-full indent-2 lg:h-[56px] outline-none
shadow-none focus:border-[#0559FD] md:py-3 md:my-2
sm:py-3 sm:my-2'
/>
</div>
<div
className='py-5 lg:grid lg:grid-cols-3 lg:gap-5 md:grid md:grid-cols-2
md:gap-5 sm:grid sm:grid-cols-2 gap-5'
>
<div className='grid grid-cols-1 gap-2'>
<label htmlFor='city' className='font-semibold'>
City
</label>
<input
type='text'
name='cities'
placeholder='Cities'
onChange={handleChange}
onBlur={handleBlur}
value={values.cities}
className='border-2 border-[#F6F6F6] outline-none
lg:w-[150px] lg:py-3 rounded text-left
focus:border-[#0559FD] md:w-[150px] md:p-2 sm:w-[150px]
sm:py-3'
/>
</div>
<div className='grid grid-cols-1 gap-2'>
<label htmlFor='state' className='font-semibold'>
State
</label>
<Field
as='select'
name='state'
onBlur={handleBlur}
value={selectedState}
onChange={(e) => setSelectedState(e.target.value)}
className='border-2 border-[#F6F6F6] outline-none
cursor-pointer lg:w-[150px] lg:py-3 rounded text-left
focus:border-[#0559FD] md:w-[150px] md:p-2 sm:w-[150px]
sm:py-3'
>
<option>--Choose State--</option>
{availableState?.states.map((e, key) => {
return (
<option value={e.name} key={key}>
{e.name}
</option>
)
})}
</Field>
</div>
<div className='grid grid-cols-1 gap-2'>
<label htmlFor='country' className='font-semibold'>
Country
</label>
<Field
as='select'
name='country'
value={selectedCountry}
onChange={(e) => setSelectedCountry(e.target.value)}
className='border-2 border-[#F6F6F6] outline-none
cursor-pointer lg:w-[150px] lg:py-3 rounded text-left
focus:border-[#0559FD] md:w-[150px] md:p-2 sm:w-[150px]
sm:py-3'
>
<option value='country'> -- Country -- </option>
{data.countries.map((value, key) => {
return (
<option value={value.name} key={key}>
{value.name}
</option>
)
})}
</Field>
</div>
</div>
</Form>
)}
</Formik>{' '}
<div className='flex gap-1 items-center lg:mb-0'>
<button onClick={() => getCurrentLocation()}> Use my current location </button>
</div>

Resources