我正尝试使用switch语句基于step
变量呈现一个多页表单以显示特定页面。令我沮丧的是,在呈现switch语句的调用之后没有任何结果。我是否遗漏了什么?
import React, { useState } from "react";
import { songValidationSchema } from "../../../../utilities/validation";
import { Form } from "../../../../utilities/components/form";
import SONG_CAPTURE_PROPERTIES from "../../../../utilities/constants/SongCaptureProperties";
import { groupSongMetaProperties } from "../../../../utilities/functions";
import SongDetailsPage from "./SongDetailsPage";
import "./SongUpload.css";
const SongUpload = () => {
const [step, setStep] = useState(1);
const groupedSongMetaProperties = groupSongMetaProperties(
SONG_CAPTURE_PROPERTIES,
4 // Into arrays of max length of 4.
);
const initialValues = {
song: "",
art: "",
trackName: "",
genre: "",
album: "",
artist: "",
publisher: "",
recordLabel: "",
releaseYear: "",
copyrightMessage: "",
subtittle: "",
comment: "",
unsynchronisedLyric: "",
};
const nextStep = () => setStep(step + 1);
const previousStep = () => setStep(step - 1);
const handleSubmit = (values) => console.log("Form Data: ", values);
const renderSongDetailPage = () => {
switch (step) {
case 1:
return (
<SongDetailsPage
inputNames={groupedSongMetaProperties[0]}
nextStep={nextStep}
previousStep={previousStep}
/>
);
case 2:
return (
<SongDetailsPage
inputNames={groupedSongMetaProperties[1]}
nextStep={nextStep}
previousStep={previousStep}
/>
);
case 3:
return (
<SongDetailsPage
inputNames={groupedSongMetaProperties[2]}
nextStep={nextStep}
previousStep={previousStep}
/>
);
case 4:
return (
<SongDetailsPage
inputNames={groupedSongMetaProperties[3]}
nextStep={nextStep}
previousStep={previousStep}
/>
);
}
};
return (
<Form
initialValues={initialValues}
onSubmit={handleSubmit}
validationSchema={songValidationSchema}
>
<h1>SongUpload</h1>
<h3>Upload Your Songs here!</h3>
{renderSongDetailPage() // This is the function calling the switch Render.}
</Form>
);
};
export default SongUpload;
下面的组件如下所示:
import React from "react";
import { FormInput } from "../../../common/forms/form";
const SongDetailsPage = ({ inputNames, nextStep, previousStep, step }) => {
const getInputType = (str, step) => {
let type = "";
switch (step) {
case 1:
switch (str) {
case "song_file":
type = "file";
break;
case "song_art":
type = "image";
break;
case "track_name":
type = "text";
break;
case "genre":
type = "text";
break;
default:
type = null;
break;
}
break;
case 2:
type = "text"; // Since all fields need text in this group
break;
case 3:
switch (str) {
case "release_year":
type = "date";
break;
case "subtittle":
type = "text";
break;
default:
type = null;
break;
}
break;
case 4:
// case "unsynchronised_lyric": -> The only case in the last one
type = null;
}
return type;
};
if (inputNames == null) return;
else
return (
<span className="input-wrapper">
{inputNames.map((key, index) => {
const type = getInputType(inputNames[index], step);
if (type !== null)
<span key={key}>
<FormInput
label={inputNames[index]}
name={
inputNames[index] === "song_file"
? "song"
: inputNames[index] === "song_art"
? "art"
: inputNames[index] === "track_name"
? "trackName"
: inputNames[index]
}
type={type}
/>
;
</span>;
else <span key={key}> Yo! </span>;
})}
</span>
);
};
export default SongDetailsPage;
最后一部分是:
import { faEye, faEyeLowVision } from "@fortawesome/free-solid-svg-icons";
import { FontAwesomeIcon } from "@fortawesome/react-fontawesome";
import React, { useEffect, useRef, useState } from "react";
import "./Form.css";
const FormInput = ({
accept,
icon,
id,
label,
onBlur,
onChange,
name,
type,
...otherProps
}) => {
const [passwordRevealed, setPasswordRevealed] = useState(false);
const inputElement = useRef(null);
const labelElement = useRef(null);
useEffect(() => {
// input-in-focus css class moves the label out of the field and shrinks it
if (inputElement.current.value !== "") {
labelElement.current.classList.add("input-in-focus");
}
});
const handleRevealPassword = () => {
setPasswordRevealed(!passwordRevealed);
if (!passwordRevealed) type = "text";
else type = "password";
inputElement.current.type = type;
};
const handleFocus = () => {
if (
document.activeElement === inputElement.current ||
inputElement.current.value !== ""
)
labelElement.current.classList.add("input-in-focus");
else labelElement.current.classList.remove("input-in-focus");
};
const handleBlur = (e) => {
if (e.target.type === "file") return;
handleFocus();
onBlur(e);
};
return (
<div className="form-input-container">
{icon && (
<span className="label-icon-container">
<FontAwesomeIcon
className="form-input-icon"
// color={defaultStyles.colors.tomato}
icon={icon}
size="lg"
/>
</span>
)}
<label>
<p ref={labelElement}>{label}</p>
<input
accept={accept}
id={id}
name={name}
onFocus={handleFocus}
onBlur={handleBlur}
onChange={onChange}
ref={inputElement}
type={type}
{...otherProps}
/>
</label>
{type === "password" && (
<span className="upendi-password-eye">
<FontAwesomeIcon
className="password-eye"
// color={defaultStyles.colors.tomato}
icon={passwordRevealed ? faEyeLowVision : faEye}
onClick={handleRevealPassword}
size="lg"
title={
passwordRevealed
? "Click To Hide Password"
: "Click To Reveal Password"
}
/>
</span>
)}
</div>
);
};
export default FormInput;
1条答案
按热度按时间nbnkbykc1#
我不能100%肯定这个建议的正确性,所以其他人应该权衡一下。但是为了达到你想要的,你需要从你的
renderSongDetailPage
返回一个函数而不是jsx
,并且把props作为一个对象传递给组件。2然后调用renderSongDetailPage
作为一个jsx
元素。请记住,renderSongDetailPage
需要使用大写的R
来表示RenderSongDetailPage
。用法:
如果我可以通过观察提出一个建议,在
RenderSongDetailPage
函数中唯一改变的是groupedSongMetaProperties
的数组项,所以你可以在main返回中呈现如下:这应该会给予你同样的结果。虽然我不知道你的项目的整个范围,所以只是一个建议。
最终,您将看到的只是一堆
if
语句,每个语句返回一个SongDetailsPage
代码沙盒:https://codesandbox.io/s/jolly-gagarin-n66xp9?file=/src/App.js