reactjs 我面临的问题,在预填充形式的挂钩

vwhgwdsa  于 4个月前  发布在  React
关注(0)|答案(1)|浏览(50)

所以,我想重用表单组件来创建和编辑meetupForm数据。但是,我面临的问题是,我想在isEdit为true时将meetupForm数据传递给meetupForm组件,并使用该数据初始化输入字段,但它并不像预期的那样工作。
使用Input钩子处理输入

import { useReducer } from "react";

const inputStateReducer = (state, action) => {
  if (action.type === "INPUT") {
    console.log(action.value);
    return { value: action.value, isTouched: state.isTouched };
  }
  if (action.type === "BLUR") {
    return { value: state.value, isTouched: true };
  }
  if (action.type === "RESET") {
    return { isTouched: false, value: "" };
  }
  return state;
};

const useInput = (validateValue, initalValue = "") => {
  const [inputState, disptach] = useReducer(inputStateReducer, {
    value: initalValue,
    isTouched: false,
  });
  console.log("inputState.value:", inputState.value);

  const valueIsValid = validateValue(inputState.value);
  const hasError = !valueIsValid && inputState.isTouched;
  const valueChangeHandler = (event) => {
    disptach({ type: "INPUT", value: event.target.value });
  };
  const isTouchHandler = (event) => {
    disptach({ type: "BLUR" });
  };
  const reset = () => {
    disptach({ type: "RESET" });
  };

  return {
    value: inputState.value,
    isValid: valueIsValid,
    hasError,
    valueChangeHandler,
    isTouchHandler,
    reset,
  };
};
export default useInput;

字符串
MeetupForm组件

import { FormLabel, TextField } from "@material-ui/core";

import { useState, useMemo, useEffect } from "react";

import useInput from "../../Hooks/useInput";
import imageIcon from "../../assests/imageicon.png";
import { useNavigate } from "react-router-dom";

const MeetUpForm = ({ url, isEdit = false, meetup }) => {
  const [currentMeetup, setCurrentMeetup] = useState(meetup);
  
  
  const [formError, setFormError] = useState(true);
  const [eventImage, setEventImage] = useState(null);
  const token = localStorage.getItem("token");
  const [shouldUpload, setShouldUpload] = useState(null); // to decide if upload should be done or not
  const [Date, setDate] = useState(null);
  const navigate = useNavigate();
  const [meetupError, setMeetupError] = useState(true);
  
  const {
    value: enteredName,
    isValid: enteredNameIsValid,
    hasError: nameInputError,
    valueChangeHandler: nameChangeHandler,
    isTouchHandler: nameBlurHandler,
    reset: resetName,
  } = useInput(
    (value) => value.trim() !== "",
    isEdit ? currentMeetup.name : ""
    );
    const {
      value: enteredAddress,
      isValid: enteredAddressIsValid,
      hasError: addressInputError,
      valueChangeHandler: addressChangeHandler,
      isTouchHandler: addressBlurHandler,
      reset: resetAddress,
    } = useInput(
      (value) => value.trim() !== "",
      isEdit ? currentMeetup.address : ""
      );
      
      const {
        value: enteredDescription,
        isValid: enteredDescriptionIsValid,
        hasError: discriptionInputError,
        valueChangeHandler: descriptionChangeHandler,
        isTouchHandler: descriptionBlurHandler,
        reset: resetDescription,
      } = useInput(
        (value) => value.trim() !== "",
        isEdit ? currentMeetup.description : ""
        );
        
        
        
        useEffect(() => {
          setCurrentMeetup(meetup);
        }, [meetup]);
        console.log("currentMeetup.name:", currentMeetup.name);
  const sumbitHandler = (event) => {
    event.preventDefault();
    console.log(enteredAddress, enteredDescription, enteredName);
    if (
      enteredDescriptionIsValid &&
      enteredAddressIsValid &&
      enteredNameIsValid
    ) {
      setShouldUpload(true);
    }
  };
  const formData = useMemo(() => {
    const data = new FormData();
    data.append("enteredAddress", enteredAddress);
    data.append("enteredName", enteredName);
    data.append("enteredDescription", enteredDescription);
    data.append("image", eventImage);
    data.append("date", Date);
    return data;
  }, [enteredAddress, enteredName, enteredDescription, eventImage, Date]);

  useEffect(() => {
    // post the data to backend

    if (!shouldUpload) return;

    const uploadData = async () => {
      try {
        const method = isEdit ? "PUT" : "POST";
        const response = await fetch(isEdit ? `${url}/${meetup.id}` : url, {
          method,
          headers: {
            Authorization: `Bearer ${token}`,
          },
          body: formData,
        });

        if (!response.ok) {
          console.log("Error:", response.status);
          setFormError(true);
        }

        const data = await response.json();
        console.log(data.message);
        if (data.message === "Meetup created successfully") {
          navigate("/home");
        }
      } catch (error) {
        console.log("Error file loading", error);
        setMeetupError(true);
      }
      setShouldUpload(false);
    };
    uploadData();
  }, [shouldUpload, formData, token, navigate, url, isEdit, meetup]);

  return (
    <div className="relative xl:3/5 flex flex-col justify-center max-xl:padding-x align-middle gap-5 max-container">
      {!formError && (
        <div className="border bg-red rounded-full">
          <h1>Something went wrong try again</h1>
        </div>
      )}
      {!meetupError && (
        <div className="border bg-red rounded-full">
          <h1>Meetup error</h1>
        </div>
      )}
      <form
        onSubmit={sumbitHandler}
        className="relative xl:3/5 flex flex-col justify-center max-xl:padding-x align-middle gap-5 max-container"
      >
        <div className="flex flex-col">
          <FormLabel className="items-start justify-start text-start font-palanquin pb-2">
            Your Name
          </FormLabel>
          <TextField
            type="text"
            fullWidth
            id="fullWidth"
            value={enteredName}
            color={nameInputError ? "primary" : "secondary"}
            variant="outlined"
            onChange={nameChangeHandler}
            onBlur={nameBlurHandler}
          ></TextField>
        </div>
        <div className="flex flex-col">
          <FormLabel className="items-start justify-start text-start font-palanquin pb-2">
            Event Address
          </FormLabel>
          <TextField
            type="text"
            value={enteredAddress}
            color={enteredAddressIsValid ? "primary" : "secondary"}
            variant="outlined"
            onChange={addressChangeHandler}
            onBlur={addressBlurHandler}
          ></TextField>
        </div>
        <FormLabel>Event's Poster</FormLabel>
        <div className="border-2 border-slate-700 rounded-md py-3 px-6">
          <input
            className="opacity-0 w-full z-5 mb-[-10px] "
            type="file"
            name="image"
            id="image"
            accept="/image*"
            onChange={(e) => {
              setEventImage(e.target.files[0]);
            }}
            alt="event poster image"
          ></input>
          <img className="w-[40px] h-[40px] z-0" src={imageIcon} alt="hello" />
        </div>
        <FormLabel>Event's Date</FormLabel>
        <TextField
          type="date"
          onChange={(e) => {
            setDate(e.target.valueAsDate);
          }}
          variant="outlined"
        ></TextField>
        <div className="flex flex-col">
          <FormLabel className="items-start justify-start text-start font-palanquin pb-2">
            Enter Event's Description
          </FormLabel>
          <textarea
            className="my-3 pb-40 pt-2 px-3 border-2 border-slate-700 rounded-md focus:ring focus:ring-blue-200"
            type="text"
            value={enteredDescription}
            color={enteredDescriptionIsValid ? "primary" : "secondary"}
            onChange={descriptionChangeHandler}
            onBlur={descriptionBlurHandler}
            row={4}
            cols={1}
          ></textarea>
        </div>
        <button
          type="submit"
          className=" bg-[#dc143c] text-center text-slate-200 rounded-full font-palanquin font-medium text-lg px-3 py-4 mx-8 "
        >
          Add Event
        </button>
      </form>
    </div>
  );
};

export default MeetUpForm;


请帮助我或建议我任何替代的方式这样做!
我尝试重用meetupform组件,但在通过自定义钩子预填充数据时遇到了问题

agxfikkp

agxfikkp1#

看起来你应该重构一下useInput钩子,这样当initialValue参数改变时,它就可以重新初始化状态值。将reducer函数移到钩子体中,这样它就可以重置为初始值,并使用useEffect钩子来分派重置操作。
范例:

const useInput = (validateValue, initialValue = "") => {

  // Reducer function moved into useInput function scope to 
  // close over initial value
  const inputStateReducer = (state, action) => {
    switch (action.type) {
      case "INPUT":
        return { ...state, value: action.value };

      case "BLUR":
        return { ...state, isTouched: true };

      case "RESET":
        // Reset to current initial value
        return { isTouched: false, value: initialValue };

      default:
        return state;
    }
  };

  const [{ isTouched, value }, dispatch] = useReducer(inputStateReducer, {
    value: initialValue,
    isTouched: false
  });

  const isValid = validateValue(value);

  const hasError = !isValid && isTouched;

  const valueChangeHandler = (event) => {
    dispatch({ type: "INPUT", value: event.target.value });
  };

  const isTouchHandler = () => {
    dispatch({ type: "BLUR" });
  };

  const reset = () => {
    dispatch({ type: "RESET" });
  };

  // Initial value changed, reset input state
  useEffect(() => {
    reset();
  }, [initialValue]);

  return {
    value,
    isValid,
    hasError,
    valueChangeHandler,
    isTouchHandler,
    reset
  };
};

字符串

Demo


的数据

相关问题