I have a counter in a Formik form. In the form, the user can increment a counter. I use setFieldValue to update the initial value of nbProducts, but when I submit the form nbProducts stays at 0. Here are the three components involved.
ProductCounter :
import { Field } from "formik"
import Image from "next/image"
import { useState } from "react"
import { Tooltip } from "../Tooltip/Tooltip"
const ProductCounter = ({ onCounterChange }) => {
const [productCounter, setProductCounter] = useState<number>(0)
const addProduct = () => {
const updatedCounter = productCounter + 1
setProductCounter(updatedCounter)
onCounterChange(updatedCounter) // Appel de la fonction onCounterChange
}
const removeProduct = () => {
if (productCounter > 0) {
const updatedCounter = productCounter - 1
setProductCounter(updatedCounter)
onCounterChange(updatedCounter) // Appel de la fonction onCounterChange
}
}
return (
<div>
<div className="mb-10">
<div className="mb-2 mt-[10px] text-xl font-bold leading-normal lg:text-2xl">
Nombre de produits éligibles<span className="text-red">*</span>
</div>
<p>
1 produit Bonux éligible = 1 cadeau. Indique ici le nombre de produits Bonux éligibles figurant sur ta preuve
d’achat.
</p>
<div className="mt-2 flex gap-2">
<div className="flex w-1/3 items-center justify-center gap-1 rounded-[30px] border-2 border-blue px-3 text-xl font-bold">
<button type="button" onClick={removeProduct} disabled={productCounter <= 0}>
<Image src="/icons/icon-arrow.svg" width={30} height={30} alt="arrow" />
</button>
<Field as="div" name="nbProducts" type="number" value={productCounter}>
{productCounter}
</Field>
<button type="button" onClick={addProduct}>
<Image src="/icons/icon-arrow.svg" width={30} height={30} alt="arrow" className="rotate-180" />
</button>
</div>
<Tooltip explainer="Ceci est une info-bulle" intent="primary" size="md" side="top" withArrow>
<button className="h-3 w-3 rounded-full bg-blue text-white">
<Image src="/icons/tooltip.svg" width={4} height={6} alt="?" className="m-auto" />
</button>
</Tooltip>
</div>
</div>
</div>
)
}
export default ProductCounter
Form:
import { Form, Formik, useFormik } from "formik"
import { validationSchema } from "./FormUtils"
import PersonalInfo from "./PersonalInfo"
import ProductCounter from "./ProductCounter"
import ShortForm, { ShortFormProps } from "./ShortForm"
// import UploadFile from "./UploadFiles"
import { Button } from "../Button/Button"
import { handleSubmit } from "@/app/api/improovApi"
const FullForm: React.FC<ShortFormProps> = ({
checkedItemsData,
setCheckedItemsData,
cards,
selectedCardId,
handleCheckboxChange,
}) => (
<div>
<p className="mb-14 text-base text-red">* Champs obligatoires</p>
<IssueForm
checkedItemsData={checkedItemsData}
setCheckedItemsData={setCheckedItemsData}
cards={cards}
selectedCardId={selectedCardId}
handleCheckboxChange={handleCheckboxChange}
/>
</div>
)
export default FullForm
interface IssueProps {
firstName: string
lastName: string
email: string
phone: string
address: string
postcode: string
city: string
nbProducts: number
checked: boolean
dotation: string
}
const IssueForm: React.FC<ShortFormProps> = ({
checkedItemsData,
setCheckedItemsData,
cards,
selectedCardId,
handleCheckboxChange,
}) => {
const InitialValues: IssueProps = {
firstName: "",
lastName: "",
email: "",
phone: "",
address: "",
postcode: "",
city: "",
nbProducts: 0,
checked: false,
dotation: "",
}
const formik = useFormik({
initialValues: InitialValues,
validationSchema: validationSchema,
onSubmit: handleSubmit,
})
const handleCounterChange = (value: number) => {
console.log("Nouvelle valeur du compteur :", value) // Ajout d'un console.log pour suivre les changements
formik.setFieldValue("nbProducts", value)
console.log("Valeur de nbProducts après mise à jour :", formik.values.nbProducts) // Ajout d'un console.log pour vérifier la valeur de nbProducts après mise à jour
}
console.log("Valeurs initiales du formulaire :", formik.values) // Ajout d'un console.log pour afficher les valeurs initiales du formulaire
return (
// Pass the useFormik() hook initial form values and a submit function that will
// be called when the form is submitted
<Formik initialValues={InitialValues} validationSchema={validationSchema} onSubmit={handleSubmit}>
<Form>
<PersonalInfo />
<ProductCounter onCounterChange={handleCounterChange} />
{/* <UploadFile /> */}
<div className="mb-5">
<ShortForm
checkedItemsData={checkedItemsData}
setCheckedItemsData={setCheckedItemsData}
cards={cards}
selectedCardId={selectedCardId}
handleCheckboxChange={handleCheckboxChange}
/>
</div>
<div className="mt-[25px] flex justify-center">
<Button className="focus:shadow-green7 px-[15px]leading-none inline-flex items-center justify-center focus:outline-none">
<button type="submit" className="uppercase">
Je confirme
</button>
</Button>
</div>
</Form>
</Formik>
)
}
HandleSubmit:
import { FormikValues } from "formik"
// Fonction pour simuler une requête AJAX
const simulateFetch = (url: string, options: any) => {
return new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest()
xhr.open(options.method || "GET", url)
xhr.onload = function () {
if (xhr.status >= 200 && xhr.status < 300) {
const response = {
ok: true,
json: () => Promise.resolve(JSON.parse(xhr.responseText)),
}
resolve(response)
} else {
const error = new Error("Network response was not ok")
reject(error)
}
}
xhr.onerror = function () {
const error = new Error("Network error occurred")
reject(error)
}
if (options.headers) {
Object.keys(options.headers).forEach((key) => {
xhr.setRequestHeader(key, options.headers[key])
})
}
xhr.send(options.body)
})
}
// Fonction pour soumettre le formulaire
export const handleSubmit = async (values: FormikValues) => {
try {
const url = "https://app-preprod.improov-www02.evolix.eu/project/bonux/issue" // Mettre l'URL correcte ici
const token = "OTLmCl5JA6CF" // Mettre le token correct ici
if (!url || !token) {
throw new Error("Missing URL or token")
}
console.log("Form values:", values) // Afficher les valeurs du formulaire dans la console
const formData = new FormData()
Object.entries(values).forEach(([key, value]) => {
console.log("Appending to formData:", key, value) // Afficher chaque clé-valeur ajoutée à formData dans la console
formData.append(key, String(value)) // Utiliser String() pour s'assurer que la valeur est de type string
})
// Envoi de la requête avec les données du formulaire
const response = (await simulateFetch(url, {
method: "POST",
body: formData,
headers: { "X-Improov-Token": token },
})) as Response
// Traitement de la réponse
const responseData = await response.json()
console.log("Response from server:", responseData)
alert("Form submitted successfully!") // Message de succès à supprimer après les tests
} catch (error) {
console.error("Error submitting form:", error)
alert("Failed to submit form. Please try again later.")
}
}
Where does that problem could come from?
Thank you