How to use Mantine dropzone with React hook form in Javascript - javascript

Is there any solution to use Mantine dropzone with Reack hook form in javascript? I am doing a modal Upload using Tailwind components like this
import { useForm } from 'react-hook-form';
import { Group, Text, useMantineTheme } from '#mantine/core';
import { Dropzone, DropzoneProps, IMAGE_MIME_TYPE } from '#mantine/dropzone';
export default function UploadForm({ isVisible, onClose }) {
const { register, handleSubmit, formState: { errors } } = useForm({});
const onSubmit = data => console.log(data);
if (!isVisible) return <></>;
return (
<div className="bg-white shadow sm:rounded-lg">
<div className="px-4 py-5 sm:p-6">
<h3 className="text-lg leading-6 font-medium text-gray-900">Create new subcategory</h3>
<div className="mt-2 max-w-xl text-sm text-gray-500">
<p>Enter subcategory's name</p>
</div>
<form onSubmit={handleSubmit(onSubmit)} className="mt-5 sm:flex sm:items-center">
<div className="w-full sm:max-w-xs">
<label htmlFor="Name" className="sr-only">
Name
</label>
<input
type="file"
{...register("file", { required: true })}
/>
</div>
<button
type="submit"
className="mt-3 w-full inline-flex items-center justify-center px-4 py-2 border border-transparent shadow-sm font-medium rounded-md text-white bg-indigo-600 hover:bg-indigo-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
>
Save
</button>
</form>
</div>
</div>
);
}
But when i tried to change the input to Mantine dropzone, it always occured error. Is there any ideas?
Thank you so much and sorry for bad English!
I want to have a modal form with only dropzone and submit button, but i'm still confusing with Mantine dropzone

For someone stuck in this problem like me, you can use Controller and FormProvider of react-hook-form to solve this problem, just replace the input tag with the code below
<Controller
control={methods.control}
name="fileupload"
render={({ field }) => (
<Dropzone
onDrop={(files) =>
methods.setValue("fileupload", files)
}
onReject={(files) =>
console.log("rejected files", files)
}
maxSize={3 * 1024 ** 2}
accept={IMAGE_MIME_TYPE}
{...field}
>
<Group
position="center"
spacing="xl"
style={{
minHeight: 220,
pointerEvents: "none",
}}
>
<Dropzone.Accept>
<IconUpload
size={50}
stroke={1.5}
color={
theme.colors[theme.primaryColor][
theme.colorScheme === "dark" ? 4 : 6
]
}
/>
</Dropzone.Accept>
<Dropzone.Reject>
<IconX
size={50}
stroke={1.5}
color={
theme.colors.red[
theme.colorScheme === "dark" ? 4 : 6
]
}
/>
</Dropzone.Reject>
<Dropzone.Idle>
<IconPhoto size={50} stroke={1.5} />
</Dropzone.Idle>
<div>
<Text size="xl" inline>
Drag images here or click to select files
</Text>
<Text
size="sm"
color="dimmed"
inline
mt={7}
>
Attach as many files as you like, each
file should not exceed 5mb
</Text>
</div>
</Group>
</Dropzone>
)}
/>
and wrap all the form in <FormProvider {...methods}></FormProvider>, change submit function to onSubmit={methods.handleSubmit()}

Related

Problem with data type in useForm InertiaJs

I have useForm like this
const form = useForm({
tech: [],
preview_image: {},
imageUrl: null,
});
Then I have image upload with preview before upload
<InputInlineMultiGroub>
<div class="py-4 md:w-1/2" v-if="form.imageUrl">
<img class="max-h-40 max-w-full transition-all duration-300 rounded-lg cursor-pointer filter grayscale hover:grayscale-0 mx-auto" :src="form.imageUrl"/>
</div>
<div v-bind:class="form.imageUrl ? 'py-4 md-w-1/2' : 'p-4 md:w-full'">
<InputLabel for="preview_image" value="Preview Image" />
<TextInput id="preview_image" type="file" class="mt-1 block w-full" required #change="imagePreviewShow" /> <InputError class="mt-2" :message="form.errors.type"/>
</div>
</InputInlineMultiGroub>
Also this method for reactive image change
const imagePreviewShow = (even) => {
const file = even.target.files[0];
form.preview_image = file;
form.imageUrl = URL.createObjectURL(file);
};
Then I have a multiselect with 'tags' mode like this
<InputGroub>
<InputLabel for="tech" value="Technology" />
<div>
<Multiselect placeholder="cari tech & hit enter" id="tech" v-model="form.tech" mode="tags" :close-on-select="true" :searchable="true" :create-option="true" :options="techList" />
</div>
</InputGroub>
My question is :
The array type in useFrom is like
this
but I needit to be like
this
please help

React Hook Form not validating nested input field until I call onChange

I have a form which has 2 fields.
Heading
Dynamic List which contains Name & Image
I'm able to validate changes whenever Heading or Name inside dynamic list is changed.
But when I change Image, the validation is failing. It returns true instead of showing error message. I tried adding a text input to test the image. Whenever I call onChange it is working fine.
Here is my code:
import { useForm } from "react-hook-form";
import { zodResolver } from "#hookform/resolvers/zod";
import * as z from "zod";
const schema = z.object({
heading: z
.string()
.min(3, { message: "Min 3 characters" })
.max(40, { message: "Max 40 characters" }),
testimonials: z.array(
z.object({
name: z.string().min(3, { message: "Min 3 characters" }),
image: z.string().url({ message: "Invalid URL" }),
})
),
});
const {
register,
handleSubmit,
formState: { errors },
} = useForm({
resolver: zodResolver(schema),
});
const [dataObj, setDataObj] = useState({
"heading": "",
"testimonials": []
});
const fetchData = () => {
// fetch list from server
// bind data
setDataObj(dataFromServer);
};
fetchData();
const listChanged = (type, value, index) => {
let list = dataObj.data.testimonials;
if (type == "name") {
list[index].name = value;
} else if (type == "image") {
list[index].image = value;
}
setDataObj({
...dataObj,
testimonials: list,
});
};
const headingChanged = (value) => {
setDataObj({
...dataObj,
heading: value,
});
};
<form className="mt-10 space-y-6" onSubmit={handleSubmit(onSubmit)}>
<div
className={`relative appearance-none block w-full px-3 py-2 border rounded-md shadow-sm placeholder-gray-400 sm:text-sm ${
errors.heading
? "border-red-400 focus:outline-none focus:ring-red-500 focus:border-red-500"
: "border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500"
}`}
>
<label
htmlFor="name"
className="absolute -top-2 left-2 -mt-px inline-block bg-white px-1 text-xs font-medium text-gray-400"
>
Section Heading
</label>
<div className="mt-1">
<input
type="text"
autoComplete="name"
{...register("heading", {
required: true,
})}
className="block w-full border-0 p-0 text-gray-900 placeholder-gray-500 focus:ring-0 sm:text-sm"
value={dataObj.data.title}
onChange={(e) => headingChanged( e.target.value)}
/>
</div>
{errors.heading && (
<small className="mt-2 text-xs text-red-500">
{errors.heading.message}
</small>
)}
</div>
<div className="mt-2 w-full py-2">
<div>
<div className="mt-2 flex justify-center mx-auto text-left">
<ul role="list" className="w-full">
{dataObj.data.testimonials.map((item, index) => (
<li key={index} className="py-3">
<div className="flex items-center space-x-4 justify-start w-full">
<div className="isolate -space-y-px rounded-md shadow-sm w-full">
<div
className={`appearance-none relative w-full px-3 py-2 border rounded-md rounded-b-none shadow-sm sm:text-sm ${
errors.testimonials?.[index]?.name
? "border-red-400 focus:outline-none focus:ring-red-500 focus:border-red-500"
: "border-gray-300 focus:outline-none focus:ring-indigo-500 focus:border-indigo-500"
}`}
>
<label
htmlFor="name"
className="absolute -top-2 left-2 -mt-px inline-block bg-white px-1 text-xs font-medium text-gray-400"
>
Name
</label>
<input
{...register(`testimonials.${index}.name`)}
type="text"
onChange={(e) => {
listChanged(index, e.target.value, "name");
}}
value={item.name}
placeholder="New Label"
className="block w-full border-0 p-1.5 text-gray-900 placeholder-gray-500 focus:ring-0 sm:text-sm"
/>
<span className="invalid-feedback text-red-500 text-xs">
{errors.testimonials?.[index]?.name?.message}
</span>
</div>
<div className="relative rounded-md rounded-t-none border border-gray-300 px-3 py-2 focus-within:ring-0 focus-within:ring-indigo-600">
<label
htmlFor="name"
className="absolute -top-2 left-2 -mt-px inline-block bg-white px-1 text-xs font-medium text-gray-400"
>
Image
</label>
<input
{...register(`testimonials.${index}.image`)}
type="text"
value={item.image}
/>
<UploadImage
size={`small-round`}
index={index}
imageUrl={item.image}
imageChanged={listChanged}
/>
<span className="invalid-feedback text-red-500 text-xs">
{errors.testimonials?.[index]?.image?.message}
</span>
</div>
</div>
</div>
</li>
))}
</ul>
</div>
</div>
</div>
</form>;
How do I solve this?
I have created following minimum example on how to use image with useFieldArray to create dynamic form. This has been created in codesandbox and tested for validation only. Let me know if you stuck anywhere or want more information.
SandBoxLink :
import React from "react";
import { useForm, useFieldArray } from "react-hook-form";
import { zodResolver } from "#hookform/resolvers/zod";
import * as z from "zod";
const MAX_FILE_SIZE = 200000;
const ACCEPTED_IMAGE_TYPES = ["image/jpeg", "image/png"];
const schema = z.object({
heading: z
.string()
.min(3, { message: "Min 3 characters" })
.max(40, { message: "Max 40 characters" }),
testimonials: z.array(
z.object({
name: z.string().min(3, { message: "Min 3 characters" }),
testimonial: z.string().min(3, { message: "Min 3 characters" }),
image: z
.any()
.refine(
(files) => files?.[0]?.size <= MAX_FILE_SIZE,
`Max image size is 2MB.`
)
.refine(
(files) => ACCEPTED_IMAGE_TYPES.includes(files?.[0]?.type),
"Only .jpg, .png formats are supported."
)
})
)
});
const App = () => {
const appendValues = {
Name: "",
testimonial: "",
image: []
};
const defaultValues = {
heading: "",
testimonials: [appendValues]
};
const {
register,
handleSubmit,
control,
formState: { errors }
} = useForm({
defaultValues,
resolver: zodResolver(schema)
});
const { fields, append, remove } = useFieldArray({
control,
name: "testimonials"
});
const onSubmit = (data) => console.log(data);
return (
<form onSubmit={handleSubmit(onSubmit)}>
<label htmlFor="heading">Heading : </label>
<input {...register("heading")} id="heading" />
<p>{errors?.heading?.message}</p>
{fields.map((field, index) => (
<div
key={field.id}
style={{
border: "1px solid black",
padding: "10px"
}}
>
<label htmlFor={`testimonials.${index}.name`}>Name : </label>
<input
id={`test.${index}.name`}
{...register(`testimonials.${index}.name`)}
/>
<p>{errors.testimonials?.[index]?.name?.message}</p>
<br />
<label htmlFor={`testimonials.${index}.testimonial`}>
Testimonial :
</label>
<input
id={`test.${index}.testimonial`}
{...register(`testimonials.${index}.testimonial`)}
/>
<p>{errors.testimonials?.[index]?.testimonial?.message}</p>
<br />
<label htmlFor={`testimonials.${index}.image`}>Image :</label>
<input
id={`test.${index}.image`}
type="file"
{...register(`testimonials.${index}.image`)}
/>
<p>{errors.testimonials?.[index]?.image?.message}</p>
<br />
<button type="button" onClick={() => remove(index)}>
Remove
</button>
</div>
))}
<button type="button" onClick={() => append(appendValues)}>
append
</button>
<input type="submit" />
</form>
);
};
export default App;

dynamic modal not working properly in Next Js

I'm implementing a modal popup for a youtube in my Next app. I'm mapping through json object and passing them into cards. and when user selects specific card it displays a modal popup. and in that popup it is passed a url for a youtube vid.
my index.js code.
const Contents = ({result , index}) => {
let router = useRouter();
const [modal, setModel] = useState(false);
const [temp, setTemp] = useState([]);
const getData = (vid)=>{
let temp = [vid];
setTemp(item =>[1, ...temp]);
return setModel(true);
}
//console.log(result.items[1].snippet.title);
return (
<div className='grid md:grid-cols-2 gap-y-6 place-items-center lg:grid-cols-4 px-5 pt-5'>
{result.items && result.items.map((res, idx)=>{
//console.log(res.snippet);
return (
<div>
{/* <ContentCard result={res} index={index} key={idx}/> */}
<div>
<div onClick={()=>getData(res.snippet.resourceId?.videoId)}>
<div className='flex flex-col hover:scale-110 hover:transition-all hover:duration-200 hover:ease-in ease-out duration-200'>
<div className=' relative snap-center rounded-lg h-40 w-64 '>
<Image
src={res.snippet.thumbnails.standard?.url || res.snippet.thumbnails.medium?.url || res.snippet.thumbnails.high?.url}
layout="fill"
objectFit="cover"
className={`h-full w-full bg-cover rounded-lg bg-no-repeat`} />
</div>
<Moment className=' text-dark-gray' date={res.snippet.publishedAt} format={"MMM Do YY"}/>
<div className=' text-sm font-thin font-serif text-med-gray'>{res.snippet.title.slice(0, 25).concat('...')}</div>
</div>
</div>
</div>
{
modal === true ? <Modal vid={temp[1]} />: ''
}
</div>
)
})}
</div>
)
}
and my modal.js
return(
<div className=" fixed inset-0 bg-bg-black bg-opacity-70 backdrop-blur-sm flex justify-center items-center">
<div className="">
<Video vid={vid} />
{/* <h1>{vid}</h1> */}
</div>
</div>
)
Video.js
const opts ={
height: '70%',
wresulthth: '70%',
playerVars: {
autoplay: 1,
}
}
return (
<YouTube videoId={vid} opts={opts}/>
);
my issue is when modal is fired up it displays the prop data, but when i use it for youtube videos it doesn't work. also uses a lot of my cpu and it lags when only modal is opened. what is the fix?

How to pass an icon as a prop?

I'm using props and I want to have "optionText" and "optionIcon" the 1st one I'm able to add but I'm not able to implement an icon as a prop
File where I'm creating props
import Icon from "#mui/material/Icon";
function HeaderMenuOptions({ optionText, OptionIcon }) {
return (
<div className="flex items-center text-center">
<Icon>{OptionIcon}</Icon>
<h1 className="py-1 my-1 hover:bg-menu-option-hover hover:text-black cursor-pointer">
{optionText}
</h1>
</div>
);
}
export default HeaderMenuOptions;
file where I'm using said props
<div className="absolute left-72 top-3 rounded-md bg-section w-[10rem] text-center">
<p className="menu-header mt-2">VIEW OPTIONS</p>
<div className="flex items-center justify-center space-x-2 mr-2 cursor-pointer hover:bg-menu-option-hover hover:hover:text-black group">
<HeaderMenuOptions optionText="Night Mode" />
<CheckBoxIcon
defaultChecked
onClick={() => alert("Light mode has not been added yet!")}
className="cursor-pointer text-blue-500"
/>
</div>
<p className="menu-header">MORE STUFF</p>
<HeaderMenuOptions optionText="Premium" OptionIcon={SecurityIcon} />
<HeaderMenuOptions optionText="TEST" />
<HeaderMenuOptions optionText="TEST" />
<HeaderMenuOptions optionText="TEST" />
<HeaderMenuOptions optionText="TEST" />
</div>
can anyone please help me. Thanks
The HeaderMenuOptions looks fine. You need to change the parent component.
You can do something like this.
<HeaderMenuOptions optionText="Premium" OptionIcon={<SecurityIcon />} />
You can use pass icon as JSX.Element from ParentComponent to TargetComponent as the following:
import AddAlertIcon from '#mui/icons-material/AddAlert';
...
const ParentComponent=()=>{
return(
....
<TargetComponent icon={<AddAlertIcon />}>
....
)
}
const TargetComponent = (props: Props) => {
return(
<span>
{props.icon}
</span>
);
}
export type Props= {
icon: JSX.Element;
};

How to render a component inside Formik form

I'm trouble and needing help from someone more senior.
I need to render a modal component when the user clicks in a link inside a Formik form. But that form already is a component, so I'm trying to render a component inside another component that is inside a bigger component. But isn't working.
The modal or still open forever (from loading the page) or didn't load at all.
Here's the code that I tried.
Form:
// Dependencies
// $FlowExpectedError[cannot-resolve-module] */
import { useRouter } from "next/router";
// $FlowExpectedError[cannot-resolve-module] */
import { AnimatePresence, motion } from "framer-motion";
// $FlowExpectedError[cannot-resolve-module] */
import { setCookie } from "nookies";
import { Modal } from "../components/Common";
// Components
// $FlowExpectedError[cannot-resolve-module] */
import { ErrorMessage, Formik, Field, Form } from "formik";
import {
Button,
Label,
FormField,
FormCheckbox,
HeadLogo,
} from "../components/Common";
// Helpers
import { axiosRequest } from "../helpers/axiosRequest";
import React, { useState } from "react";
import literals from "../utils/literals";
const GENDERS = [
{
label: "Female",
val: "female",
},
{
label: "Male",
val: "male",
},
{
label: "Other",
val: "other",
},
];
const ModalCloseButton = ({ closeCallback }) => (
<div>
<button
type="button"
className="float-right p-5 focus:outline-none"
onClick={closeCallback}
>
{/* $FlowExpectedError[cannot-resolve-name] */}
<img
src="/icons/close.svg"
alt="Close icon"
className="float-right w-4"
/>
</button>
</div>
);
const TermsModal = ({ closeCallback }) => (
// $FlowExpectedError[cannot-resolve-name]
<>
<ModalCloseButton closeCallback={closeCallback} />
<span className="px-5 pb-5 text-lg font-bold leading-none">
{literals.SEND_TO_FRIEND}
</span>
<div className="botton justify-center">
<Button label={literals.ACCEPT} onClick={closeCallback} style="icon" />
</div>
</>
);
const SignupForm = ({
validateForm,
submitForm,
setCheckedGender,
checkedGender,
openModal,
cancelModal,
}) => (
<Formik
initialValues={{
name: "",
surnames: "",
email: "",
phone: "",
birthDate: "",
gender: "",
password: "",
terms: false,
}}
validate={validateForm}
onSubmit={submitForm}
>
{({ isSubmitting, setFieldValue, values }) => {
function handleGenderSelection(value) {
setCheckedGender(value);
setFieldValue("gender", value);
}
return (
<Form className="flex flex-col w-full space-y-2">
{/* $FlowExpectedError[cannot-resolve-name] */}
<FormField
name="name"
inputType="text"
className="text-input-bis focus:outline-none"
inputPlaceholder={literals.NAME}
/>
<FormField
name="surnames"
inputType="text"
className="text-input-bis focus:outline-none"
inputPlaceholder={literals.SURNAME}
/>
<FormField
name="email"
inputType="email"
className="text-input-bis focus:outline-none"
inputPlaceholder={literals.EMAIL}
/>
<FormField
name="password"
inputType="password"
className="text-input-bis focus:outline-none"
inputPlaceholder={literals.PASSWORD}
/>
<FormField
name="phone"
inputType="tel"
className="text-input-bis focus:outline-none"
inputPlaceholder={literals.PHONE_NUMBER}
/>
<FormField
name="birthDate"
inputType="date"
className="text-input-bis focus:outline-none"
inputPlaceholder={literals.BIRTHDATE}
/>
<div role="group" className="signup-radio">
{GENDERS.map((gender) => {
return (
<label
key={gender.val}
className={`
px-4 pt-3 pb-2 mr-2 border border-white rounded-gender leading-snug transition-colors duration-200
${
checkedGender && gender.val === checkedGender
? "bg-lightBlue"
: "transparent"
}
`}
>
<Field
type="radio"
name="gender"
value={gender.val}
checked={checkedGender === gender.val}
onChange={() => {
handleGenderSelection(gender.val);
}}
/>
<p className="text-sm text-white uppercase">{gender.label}</p>
</label>
);
})}
<ErrorMessage
name="gender"
component="div"
className="error-message"
/>
</div>
<div className="flex flex-row items-center justify-start">
<FormCheckbox
label={
<p className="ml-2 text-sm text-lightBlue">
{literals.ACCEPT_THE}
<a
href="#"
className="text-white underline"
onClick={cancelModal()}
>
{literals.TERMS_TITLE}
</a>
</p>
}
name="terms"
callback={() => setFieldValue("terms", !values.terms)}
callbackValue={!values.terms}
fillColor="lightBlue"
value={values.terms}
marginBottom="4"
/>
</div>
<div className="pb-4">
<Button type="submit" label={literals.SIGNUP} />
</div>
{/* <div className="flex flex-col items-stretch justify-start h-vh-5 flex-1 px-5 pb-5">
<div className="flex flex-col flex-1 mt-12">
<a
href={literals.GLOBAL_TERMS}
target="_blank"
className="text-xl font-bold leading-tight"
>
<u>Download</u> our Terms & Conditions
</a>
</div>
<div className="botton justify-center">
<Button
label={literals.ACCEPT}
onClick={() => setShowModal(false)}
style="icon"
/>
</div>
</div>
</Modal>
</AnimatePresence> */}
</Form>
);
}}
</Formik>
);
function Signup(): React$Node {
const [checkedGender, setCheckedGender] = useState();
const [showModal, setShowModal] = useState();
function cancelModal() {
console.log("fechar");
setShowModal(false);
}
function openModal() {
console.log("abrir");
setShowModal(true);
}
// TODO: Review validation
function validateForm(values) {
const errors = {};
if (!values.name) {
errors.name = "Required";
}
if (!values.surnames) {
errors.surnames = "Required";
}
if (!values.email) {
errors.email = "Required";
}
if (!values.password) {
errors.password = "Required";
}
if (!values.phone) {
errors.phone = "Required";
}
if (!values.birthDate) {
errors.birthDate = "Required";
}
if (!values.gender) {
errors.gender = "Required";
}
if (!values.terms) {
errors.terms = "Required";
}
return errors;
}
async function submitForm(body, { setErrors }) {
const res = await axiosRequest({
method: "POST",
url: "/auth/register",
data: body,
});
if (res?.accessCookie) {
const accessCookie = res.accessCookie;
const refreshCookie = res.refreshCookie;
setCookie(null, "accessToken", accessCookie.token, accessCookie.options);
setCookie(
null,
"refreshToken",
refreshCookie.token,
refreshCookie.options
);
router.reload();
} else {
const errorData = res?.error?.response?.data || {};
setErrors({ [errorData.field]: errorData.error });
}
}
return (
<motion.div
className="flex flex-col min-h-full"
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
<HeadLogo />
<div className="grid w-full min-h-screen grid-cols-4 gap-4 px-5 rounded-background bg-purple">
<div className="col-span-3 col-start-1 text-white mt-28">
<h1 className="w-full mb-3 font-bold leading-none text-40px">
{literals.SIGNUP_TITLE}
</h1>
<p className="w-full text-base font-light">
{literals.SIGNUP_SUBTITLE}
</p>
</div>
<div className="flex-col w-full col-span-4">
{/* $FlowExpectedError[cannot-resolve-name] */}
<SignupForm
validateForm={validateForm}
submitForm={submitForm}
setCheckedGender={setCheckedGender}
checkedGender={checkedGender}
openModal={openModal}
cancelModal={cancelModal}
/>
<Modal cancelCallback={cancelModal} closeCallback={cancelModal}>
<TermsModal closeCallback={cancelModal} />
</Modal>
</div>
</div>
</motion.div>
);
}
export default Signup;
This is the component Modal:
// #flow
import { Button } from "./Button";
// $FlowExpectedError[cannot-resolve-module]
import { motion } from "framer-motion";
type Props = {
children: any,
cancelCallback?: function,
closeCallback: function,
}
export const Modal = ({
children,
cancelCallback,
closeCallback,
}: Props): React$Node => {
return (
// $FlowExpectedError
<motion.div
className="fixed inset-0 z-50 px-5 py-16 overflow-hidden bg-darkBlue bg-opacity-90 text-darkBlue"
onClick={cancelCallback || closeCallback}
initial={{ opacity: 0 }}
animate={{ opacity: 1 }}
exit={{ opacity: 0 }}
>
{/* $FlowExpectedError */}
<motion.div
className="flex flex-col items-stretch justify-start max-h-full overflow-y-auto bg-white rounded-card"
onClick={e => e.stopPropagation()}
initial={{ y: 64, opacity: 0 }}
animate={{ y: 0, opacity: 1 }}
exit={{ y: 0, opacity: 0 }}
transition={{
type: "spring",
duration: 0.5,
bounce: 0,
}}
>
{children}
</motion.div>
</motion.div>
);
};
I don't really understand what you are trying to do. If you like to define const you can do it.
In the "component Modal:" just before return, you can define const and useState or whatever you want. But these constants will be accessible only in <Modal>.
Of course, there are components that must be on the top of the tree, for example, some initial constants and props.
P.S in nextjs you have <Link> component to your internal website routes:
<Link href={'/homepage'}>
some stuff
</Link>
You can share some screens of behaviour for future investigation.

Categories

Resources