设置状态会导致输入字段的更新。

huangapple go评论70阅读模式
英文:

setting state breaks the update of input fields

问题

I can translate the code part for you:

// Typing
type EleventlyEvent = {
  event: Event;
  event_title: string;
};

function TicketSelection({ event }: EleventlyEvent) {
  // ...
  // (The rest of the code remains the same)
  // ...
}

export default TicketSelection;

Please let me know if you need translations for specific parts or if you have any other questions.

英文:

i'm running into an issue where whenever i set the const buyFormData, the array do get updated but the rest of the code ( updating the Input Fields ) stop working. there is no javascript error. The code just hangs there. on my child component, i'm able to console.log and display the new array. however since the code stop updating it only works the first time i click on a "plus" or "minus" button.

commenting :" setBuyFormData(updatedValues);" allows the inputs to update freely but never updates the values for the child component.

how do i debug this ?
There is no error in the javascript console.

I'm using NextJs 13.

Edit : Formatted the code with Prettier.
I'm a bit desperated, i've been trying to figure this out for almost a week. Any help is welcome.

'use client';
import React from 'react';
import { MinusIcon, PlusIcon } from '@heroicons/react/20/solid';
import { useEffect, useState } from 'react';
import { FieldValues, useForm, useFormContext } from 'react-hook-form';
import TicketSummaryCard from './TicketSummaryCard';
//Typing
type EleventlyEvent = {
event: Event;
event_title: string;
};
function TicketSelection({ event }: EleventlyEvent) {
const readFormData = useFormContext();
const [buyformData, setBuyFormData] = useState([{}]);
useEffect(() => {}, [buyformData]);
const [formFields, setFormFields] = useState([
{
id: '0',
ticketName: 'Régulier',
description: 'Régulier',
price: '40.00',
limit: '5'
},
{
id: '1',
ticketName: 'Admission',
description: 'Ceci est une description Admission',
price: '10.00',
limit: '10'
},
{
id: '2',
ticketName: 'VIP',
description: 'Ceci est une description VIP',
price: '80.00',
limit: '1'
},
{
id: '3',
ticketName: 'ENFANT',
description: 'Voici le billet pour enfant',
price: '25.00',
limit: '2'
}
]);
const handleTicketChange = (e: any, action: string) => {
//Get the ticket Limit number from the input field data* attribute
let buyLimit: number = e.getAttribute('data-limit');
let fieldName: string = e.name;
let fieldCurrentValue: number = parseInt(e.value);
switch (action) {
case 'plus':
if (fieldCurrentValue < buyLimit) {
let updatedValue: number = fieldCurrentValue + 1;
e.value = updatedValue;
setValue(fieldName, updatedValue);
} else {
//Error Message for Limit reached
return;
}
break;
case 'minus':
if (fieldCurrentValue > 0) {
let updatedValue: number = fieldCurrentValue - 1;
e.value = updatedValue;
setValue(fieldName, updatedValue);
} else {
//Error Message for Limit below minimum
return;
}
break;
}
//After doing the maths update the buy list for the summary card
updateBuyList();
};
const updateBuyList = () => {
//Read all form
let tempBuyList: FieldValues = readFormData.getValues();
let updatedValues: {
ticketName: string;
ticketPrice: number;
ticketNumber: number;
}[] = [];
for (var key in tempBuyList) {
//Loop through the FieldValues in the forms
if (tempBuyList.hasOwnProperty(key)) {
formFields?.map((formField, index) => {
if (key === formField.ticketName) {
let newValues = {
ticketName: key,
ticketPrice: formField.price,
ticketNumber: tempBuyList[key]
};
//Only add the ticket to the array if the number is defined
if (tempBuyList[key]) {
updatedValues.push(newValues);
}
}
});
}
}
//This breaks the rest of the form. if i update the value the forms break but the value gets passed only for the firstime.
setBuyFormData(updatedValues);
};
const updateTicketNumber = (target) => {};
const {
register,
setValue,
formState: { errors }
} = useFormContext();
return (
<>
<main className="bg-white">
<div className="mx-auto max-w-8xl px-4 sm:px-2">
<div className="py-12 grid max-w-2xl grid-cols-1 grid-rows-1 items-start gap-x-8 gap-y-8 lg:mx-0 lg:max-w-none lg:grid-cols-12">
<div className="col-span-7 lg:col-span-9 lg:col-start-1 lg:row-end-1">
<h1 className="text-black font-semibold text-3xl">
Selection de billets
</h1>
<div className="">
{formFields.map((item, index) => (
<div
className="rounded-lg bg-white shadow-sm ring-1 ring-gray-900/5 my-10"
key={index}
>
<dl className="flex flex-wrap">
<div className="flex-auto pl-6 pt-6">
<span className="text-base font-semibold leading-6 text-gray-900">
{item.ticketName}
</span>
</div>
<div className="flex-none self-end px-6 pt-4">
<div className="mt-5 sm:ml-6 sm:mt-0 sm:flex sm:flex-shrink-0 sm:items-center">
<div className="flex flex-row" key={index}>
<button
type="button"
onClick={(e) => {
handleTicketChange(
e.currentTarget.nextSibling,
'minus'
);
}}
className="rounded-sm bg-[#33DEBD] p-1.5 text-black shadow-sm hover:bg-primaryhover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600"
>
<MinusIcon
className="h-3 w-3 rounded"
aria-hidden="true"
/>
</button>
<input
className="mx-auto w-12 p-0 m-0 text-center border-0 text-gray-900 bg-transparent font-semibold"
id={item.id}
data-limit={item.limit}
value={0}
{...register(item.ticketName)}
/>
<button
type="button"
onClick={(e) => {
handleTicketChange(
e.currentTarget.previousSibling,
'plus'
);
}}
className="rounded-sm bg-[#33DEBD] p-1.5 text-black shadow-sm hover:bg-primaryhover focus-visible:outline focus-visible:outline-2 focus-visible:outline-offset-2 focus-visible:outline-teal-600"
>
<PlusIcon
className="h-3 w-3 rounded"
aria-hidden="true"
/>
</button>
</div>
</div>
</div>
</dl>
<div className="mt-6 border-t border-gray-900/5 px-6 py-6">
<dt className="text-md font-semibold leading-6 text-gray-900">
{item.price}
</dt>
<dl className="leading-6 font-normal text-gray-500">
{item.description}
</dl>
</div>
</div>
))}
</div>
</div>
{/* Ticket Price summary */}
<div className="col-span-7 lg:col-span-7 lg:row-end-1 ">
<TicketSummaryCard event={event} buylist={buyformData} />
</div>
</div>
</div>
</main>
</>
);
}
export default TicketSelection;

答案1

得分: 1

我为您制作了一个带注释的版本,有效地利用了React的状态。实际上,我没有改变太多,但最值得注意的是:

  • 在组件之外使用静态数据集来表示可能的票和它们的配置(这也可以来自API)。
  • 通过复制该静态状态来创建一个表单状态,这样您可以使用它来呈现您的表单。
  • 使用react-hook-form来设置初始值和进行基本验证。
  • 当用户与表单输入进行交互时更新状态。
  • 将状态传递给票务摘要。

希望它能帮助您继续您的工作。您可以在这个Sandbox中找到代码,以便进行测试。

祝你好运!

英文:

I made you an annotated version that effectively leverages React's state. I didn't change that much, actually, but most notably:

  • Use a static dataset for the possible tickets and their configuration outside the component (this could come from an API as well).
  • Create a form state by making a copy of that static state so you can use that to render your form.
  • Use react-hook-form for 1) setting initial values, and 2) doing basic validations.
  • Update the state when the user interacts with the form input.
  • Pass along the state to the ticket summary.

I hope it helps you continue your journey to make this work. The code is available in this Sandbox so you can play around with it.

Good luck!

huangapple
  • 本文由 发表于 2023年5月22日 15:46:25
  • 转载请务必保留本文链接:https://go.coder-hub.com/76304001.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定