我们可以通过跟踪您在TopForm
中使用callback
props 的位置来看到问题的问题:
onClick={() => callback(dayText, monthText, yearText)}
将callback
作为callback={[setDayValue, setMonthValue, setYearValue]}
传递意味着callback
是一个数组,因此您试图将数组作为函数调用,这是不正确的.
相反,您可以单独调用数组的内部函数,如:
onClick={() => {
callback[0](dayText)
callback[1](monthText)
callback[2](yearText)
}}
const { useState } = React;
function TopForm({ callback }) {
const [error, setError] = useState(false);
const [dayText, setDayText] = useState("");
const [monthText, setMonthText] = useState("");
const [yearText, setYearText] = useState("");
const handleSubmit = (event) => {
event.preventDefault();
setDayText("");
setMonthText("");
setYearText("");
};
return (
// Inputs Container
<form onSubmit={handleSubmit}>
{/* Upper Form */}
<div className="container flex justify-center gap-4 md:max-w-lg">
<div className="container w-1/3 flex flex-col">
<label
htmlFor="day"
className={`if ${error} ? "text-red-400 text-sm mb-1 uppercase tracking-wide" : "text-smokey-grey"`}
id="day-label"
>
Day
</label>
<input
type="number"
name="day"
id="day"
required
className="border-solid border-2 border-light-grey rounded-md p-3 text-lg outline-none focus:border-purple"
onChange={(event) => setDayText(event.target.value)}
value={dayText}
/>
<div id="day-error" className="hidden text-xs text-red-400 mt-2">
Must be a valid date
</div>
</div>
<div className="container w-1/3 flex flex-col">
<label
htmlFor="month"
id="month-label"
className="text-smokey-grey text-sm mb-1 uppercase tracking-wide"
>
Month
</label>
<input
type="number"
name="month"
id="month"
required
className="border-solid border-2 border-light-grey rounded-md p-3 text-lg outline-none focus:border-purple"
onChange={(event) => setMonthText(event.target.value)}
value={monthText}
/>
<div id="month-error" className="hidden text-xs text-red-400 mt-2">
Must be a valid date
</div>
</div>
<div className="container w-1/3 flex flex-col">
<label
htmlFor="year"
id="year-label"
className="text-smokey-grey text-sm mb-1 uppercase tracking-wide"
>
Year
</label>
<input
type="number"
name="year"
id="year"
required
className="border-solid border-2 border-light-grey rounded-md p-3 text-lg outline-none focus:border-purple"
onChange={(event) => setYearText(event.target.value)}
value={yearText}
/>
<div id="year-error" className="hidden text-xs text-red-400 mt-2">
Must be a valid date
</div>
</div>
</div>
{/* Line Arrow Container */}
<div className="container my-20 flex justify-center relative">
<hr className="border-light-grey w-full" />
<button
id="button"
className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-purple w-16 h-16 rounded-full flex items-center justify-center hover:scale-125 transition-all"
type="submit"
onClick={() => {
callback[0](dayText)
callback[1](monthText)
callback[2](yearText)
}}
>
<img src="/images/icon-arrow.svg" alt="arrow" className="w-6" />
</button>
</div>
</form>
);
}
function Results({ dayValue, monthValue, yearValue }) {
return (
// Results Container
<div id="results-container" className="container">
{/* Individual Container */}
<div className="container flex">
<span
id="results-year"
className="text-5xl italic font-bold text-purple mr-2"
>
{yearValue}
</span>
<p className="text-5xl italic font-bold mr-2">years</p>
</div>
<div className="container flex">
<span
id="results-month"
className="text-5xl italic font-bold text-purple mr-2"
>
{monthValue}
</span>
<p className="text-5xl italic font-bold mr-2">months</p>
</div>
<div className="container flex">
<span
id="results-day"
className="text-5xl italic font-bold text-purple mr-2"
>
{dayValue}
</span>
<p className="text-5xl italic font-bold mr-2">days</p>
</div>
</div>
);
}
function Hero() {
const [dayValue, setDayValue] = useState("--");
const [monthValue, setMonthValue] = useState("--");
const [yearValue, setYearValue] = useState("--");
return (
<div className="font-poppins bg-light-grey p-2 h-screen w-screen">
{/* Main Container */}
<div className="container bg-white mt-16 max-w-[95%] md:max-w-2xl mx-auto p-10 rounded-xl rounded-br-3xl">
<TopForm
callback={[setDayValue, setMonthValue, setYearValue]}
/>
<Results
dayValue={dayValue}
monthValue={monthValue}
yearValue={yearValue}
/>
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById("app")).render(<Hero />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="app"></div>
或者,您可以在Hero
中创建一个回调函数,该函数接受三个参数并调用状态函数本身:
function Hero () {
// …
const setValues = (day, month, year) => {
setDayValue(day);
setMonthValue(month);
setYearValue(year);
};
// …
<TopForm callback={setValues} />
const { useState } = React;
function TopForm({ callback }) {
const [error, setError] = useState(false);
const [dayText, setDayText] = useState("");
const [monthText, setMonthText] = useState("");
const [yearText, setYearText] = useState("");
const handleSubmit = (event) => {
event.preventDefault();
setDayText("");
setMonthText("");
setYearText("");
};
return (
// Inputs Container
<form onSubmit={handleSubmit}>
{/* Upper Form */}
<div className="container flex justify-center gap-4 md:max-w-lg">
<div className="container w-1/3 flex flex-col">
<label
htmlFor="day"
className={`if ${error} ? "text-red-400 text-sm mb-1 uppercase tracking-wide" : "text-smokey-grey"`}
id="day-label"
>
Day
</label>
<input
type="number"
name="day"
id="day"
required
className="border-solid border-2 border-light-grey rounded-md p-3 text-lg outline-none focus:border-purple"
onChange={(event) => setDayText(event.target.value)}
value={dayText}
/>
<div id="day-error" className="hidden text-xs text-red-400 mt-2">
Must be a valid date
</div>
</div>
<div className="container w-1/3 flex flex-col">
<label
htmlFor="month"
id="month-label"
className="text-smokey-grey text-sm mb-1 uppercase tracking-wide"
>
Month
</label>
<input
type="number"
name="month"
id="month"
required
className="border-solid border-2 border-light-grey rounded-md p-3 text-lg outline-none focus:border-purple"
onChange={(event) => setMonthText(event.target.value)}
value={monthText}
/>
<div id="month-error" className="hidden text-xs text-red-400 mt-2">
Must be a valid date
</div>
</div>
<div className="container w-1/3 flex flex-col">
<label
htmlFor="year"
id="year-label"
className="text-smokey-grey text-sm mb-1 uppercase tracking-wide"
>
Year
</label>
<input
type="number"
name="year"
id="year"
required
className="border-solid border-2 border-light-grey rounded-md p-3 text-lg outline-none focus:border-purple"
onChange={(event) => setYearText(event.target.value)}
value={yearText}
/>
<div id="year-error" className="hidden text-xs text-red-400 mt-2">
Must be a valid date
</div>
</div>
</div>
{/* Line Arrow Container */}
<div className="container my-20 flex justify-center relative">
<hr className="border-light-grey w-full" />
<button
id="button"
className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-purple w-16 h-16 rounded-full flex items-center justify-center hover:scale-125 transition-all"
type="submit"
onClick={() => callback(dayText, monthText, yearText)}
>
<img src="/images/icon-arrow.svg" alt="arrow" className="w-6" />
</button>
</div>
</form>
);
}
function Results({ dayValue, monthValue, yearValue }) {
return (
// Results Container
<div id="results-container" className="container">
{/* Individual Container */}
<div className="container flex">
<span
id="results-year"
className="text-5xl italic font-bold text-purple mr-2"
>
{yearValue}
</span>
<p className="text-5xl italic font-bold mr-2">years</p>
</div>
<div className="container flex">
<span
id="results-month"
className="text-5xl italic font-bold text-purple mr-2"
>
{monthValue}
</span>
<p className="text-5xl italic font-bold mr-2">months</p>
</div>
<div className="container flex">
<span
id="results-day"
className="text-5xl italic font-bold text-purple mr-2"
>
{dayValue}
</span>
<p className="text-5xl italic font-bold mr-2">days</p>
</div>
</div>
);
}
function Hero() {
const [dayValue, setDayValue] = useState("--");
const [monthValue, setMonthValue] = useState("--");
const [yearValue, setYearValue] = useState("--");
const setValues = (day, month, year) => {
setDayValue(day);
setMonthValue(month);
setYearValue(year);
};
return (
<div className="font-poppins bg-light-grey p-2 h-screen w-screen">
{/* Main Container */}
<div className="container bg-white mt-16 max-w-[95%] md:max-w-2xl mx-auto p-10 rounded-xl rounded-br-3xl">
<TopForm callback={setValues} />
<Results
dayValue={dayValue}
monthValue={monthValue}
yearValue={yearValue}
/>
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById("app")).render(<Hero />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="app"></div>
或者,您可以将这些函数作为单独的props 传递:
<TopForm
setDay={setDayValue}
setMonth={setMonthValue}
setYear={setYearValue}
/>
function TopForm({ setDay, setMonth, setYear }) {
// …
onClick={() => {
setDay(dayText)
setMonth(monthText)
setYear(yearText)
}}
// …
}
const { useState } = React;
function TopForm({ setDay, setMonth, setYear }) {
const [error, setError] = useState(false);
const [dayText, setDayText] = useState("");
const [monthText, setMonthText] = useState("");
const [yearText, setYearText] = useState("");
const handleSubmit = (event) => {
event.preventDefault();
setDayText("");
setMonthText("");
setYearText("");
};
return (
// Inputs Container
<form onSubmit={handleSubmit}>
{/* Upper Form */}
<div className="container flex justify-center gap-4 md:max-w-lg">
<div className="container w-1/3 flex flex-col">
<label
htmlFor="day"
className={`if ${error} ? "text-red-400 text-sm mb-1 uppercase tracking-wide" : "text-smokey-grey"`}
id="day-label"
>
Day
</label>
<input
type="number"
name="day"
id="day"
required
className="border-solid border-2 border-light-grey rounded-md p-3 text-lg outline-none focus:border-purple"
onChange={(event) => setDayText(event.target.value)}
value={dayText}
/>
<div id="day-error" className="hidden text-xs text-red-400 mt-2">
Must be a valid date
</div>
</div>
<div className="container w-1/3 flex flex-col">
<label
htmlFor="month"
id="month-label"
className="text-smokey-grey text-sm mb-1 uppercase tracking-wide"
>
Month
</label>
<input
type="number"
name="month"
id="month"
required
className="border-solid border-2 border-light-grey rounded-md p-3 text-lg outline-none focus:border-purple"
onChange={(event) => setMonthText(event.target.value)}
value={monthText}
/>
<div id="month-error" className="hidden text-xs text-red-400 mt-2">
Must be a valid date
</div>
</div>
<div className="container w-1/3 flex flex-col">
<label
htmlFor="year"
id="year-label"
className="text-smokey-grey text-sm mb-1 uppercase tracking-wide"
>
Year
</label>
<input
type="number"
name="year"
id="year"
required
className="border-solid border-2 border-light-grey rounded-md p-3 text-lg outline-none focus:border-purple"
onChange={(event) => setYearText(event.target.value)}
value={yearText}
/>
<div id="year-error" className="hidden text-xs text-red-400 mt-2">
Must be a valid date
</div>
</div>
</div>
{/* Line Arrow Container */}
<div className="container my-20 flex justify-center relative">
<hr className="border-light-grey w-full" />
<button
id="button"
className="absolute top-1/2 left-1/2 transform -translate-x-1/2 -translate-y-1/2 bg-purple w-16 h-16 rounded-full flex items-center justify-center hover:scale-125 transition-all"
type="submit"
onClick={() => {
setDay(dayText)
setMonth(monthText)
setYear(yearText)
}}
>
<img src="/images/icon-arrow.svg" alt="arrow" className="w-6" />
</button>
</div>
</form>
);
}
function Results({ dayValue, monthValue, yearValue }) {
return (
// Results Container
<div id="results-container" className="container">
{/* Individual Container */}
<div className="container flex">
<span
id="results-year"
className="text-5xl italic font-bold text-purple mr-2"
>
{yearValue}
</span>
<p className="text-5xl italic font-bold mr-2">years</p>
</div>
<div className="container flex">
<span
id="results-month"
className="text-5xl italic font-bold text-purple mr-2"
>
{monthValue}
</span>
<p className="text-5xl italic font-bold mr-2">months</p>
</div>
<div className="container flex">
<span
id="results-day"
className="text-5xl italic font-bold text-purple mr-2"
>
{dayValue}
</span>
<p className="text-5xl italic font-bold mr-2">days</p>
</div>
</div>
);
}
function Hero() {
const [dayValue, setDayValue] = useState("--");
const [monthValue, setMonthValue] = useState("--");
const [yearValue, setYearValue] = useState("--");
return (
<div className="font-poppins bg-light-grey p-2 h-screen w-screen">
{/* Main Container */}
<div className="container bg-white mt-16 max-w-[95%] md:max-w-2xl mx-auto p-10 rounded-xl rounded-br-3xl">
<TopForm
setDay={setDayValue}
setMonth={setMonthValue}
setYear={setYearValue}
/>
<Results
dayValue={dayValue}
monthValue={monthValue}
yearValue={yearValue}
/>
</div>
</div>
);
}
ReactDOM.createRoot(document.getElementById("app")).render(<Hero />);
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/18.2.0/umd/react.production.min.js" integrity="sha512-8Q6Y9XnTbOE+JNvjBQwJ2H8S+UV4uA6hiRykhdtIyDYZ2TprdNmWOUaKdGzOhyr4dCyk287OejbPvwl7lrfqrQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/18.2.0/umd/react-dom.production.min.js" integrity="sha512-MOCpqoRoisCTwJ8vQQiciZv0qcpROCidek3GTFS6KTk2+y7munJIlKCVkFCYY+p3ErYFXCjmFjnfTTRSC1OHWQ==" crossorigin="anonymous" referrerpolicy="no-referrer"></script>
<div id="app"></div>