NodeJS 如何用switch语句有条件地呈现react函数组件?

vuv7lop3  于 2023-01-04  发布在  Node.js
关注(0)|答案(1)|浏览(146)

我正尝试使用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;
nbnkbykc

nbnkbykc1#

我不能100%肯定这个建议的正确性,所以其他人应该权衡一下。但是为了达到你想要的,你需要从你的renderSongDetailPage返回一个函数而不是jsx,并且把props作为一个对象传递给组件。2然后调用renderSongDetailPage作为一个jsx元素。请记住,renderSongDetailPage需要使用大写的R来表示RenderSongDetailPage

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,
      });
  }
};

用法:

<RenderSongDetailPage/>

如果我可以通过观察提出一个建议,在RenderSongDetailPage函数中唯一改变的是groupedSongMetaProperties的数组项,所以你可以在main返回中呈现如下:

<SongDetailsPage
  inputNames={groupedSongMetaProperties[step-1]}
  nextStep={nextStep}
  previousStep={previousStep}
/>;

这应该会给予你同样的结果。虽然我不知道你的项目的整个范围,所以只是一个建议。
最终,您将看到的只是一堆if语句,每个语句返回一个SongDetailsPage
代码沙盒:https://codesandbox.io/s/jolly-gagarin-n66xp9?file=/src/App.js

相关问题