React-hook-form: Reset / Empty An Input File

208 views Asked by At

I am new to React and I want to create a button to reset/empty the input file for edit functionality. I am using MUI and React-hook-form. When I clicked the reset button, the image had already changed, and the input file also stated 'No file chosen', however when I clicked the submit button, the file was still there and sent to my backend. However, it should be null and hence will not be sent to the backend.

I am trying by using useRef and setting the value of the input file to null, I tried console.log for checking, and the value is null. But the value sent is still the latest image I uploaded. This is my full code:

import React, { useState, useEffect, useRef } from "react";
import { Box, TextField, IconButton } from "@mui/material";
import LoopIcon from "@mui/icons-material/Loop";
import { Controller } from "react-hook-form";

export default function MyInput(props) {
  const { name, control, label, width, image } = props;
  const [file, setFile] = useState();
  const inputFile = useRef(null);

  const handleReset = () => {
    if (inputFile.current) {
      inputFile.current.value = null;
      setFile(null);
    }
  };

  return (
    <Box sx={{ width: { width } }}>
      <Controller
        name={name}
        control={control}
        render={({ field: { onChange, value }, fieldState: { error } }) => (
          <>
            <Box>
              <TextField
                inputRef={inputFile}
                sx={{ maxWidth: "75%" }}
                onChange={(e) => {
                  onChange(e.target.files[0]);
                  setFile(URL.createObjectURL(e.target.files[0]));
                }}
                id="outlined-basic"
                label={label}
                variant="outlined"
                value={value?.fileName}
                type="file"
                InputLabelProps={{
                  shrink: true,
                  accept: "image/png, image/jpeg",
                }}
                error={!!error}
                helperText={error?.message}
              />
              <IconButton onClick={handleReset}>
                <LoopIcon />
              </IconButton>
            </Box>
            <img
              className="image"
              src={file ? file : image}
              alt={file ? "Error: Image cannot be displayed" : undefined}
              style={{ maxWidth: "100%", height: "auto", marginTop: "20px" }}
            />
          </>
        )}
      />
    </Box>
  );

}

I am new to resetField, I don't know exactly how to pass it to another file, the above code is myInput.jsx, and this is the part of code where I am calling it, where should I pass the resetField?

const { handleSubmit, setValue, setError, control, resetField } = 

useForm({
    resolver: yupResolver(schema),
  });
return (
    <form onSubmit={handleSubmit(submission)}>
        <MyInput
            label="Image"
            name="image"
            control={control}
            width={"35%"}
            image={image}
         />
    </form>
)

Any idea how to make the value of my input file become null when I click the reset button? What am I missing. Thank you for your help.

1

There are 1 answers

3
Irving Armenta On

First of all, you do not need to use vanillajs selectors in React, I hope you are using that of something as a "last resort" thing.

You are using react-hook-form , so there is no need to manage the state yourself.

I am not familiar with MUI, so I am not sure exactly how the <TextField /> works.

it seems to me that if you are using something like react-hook-form you need to reset the data there, and not locally in the input with some hardcoded useState()

I would need more information about the implementation outside this component, but basically the useForm() hook from react-hook-form has a resetField() and reset() method that you can access to "reset" this data, additionally if you have access to the "control".

reset: https://react-hook-form.com/docs/useform/reset
resetField: https://react-hook-form.com/docs/useform/resetfield

The useEffect() hook in there does not have any meaning really, you could get rid of it, these 3 constants here also should not have any "control" over, You should control the state of the form and of the Field with useForm()>

// these should/can be removed.
const [file, setFile] = useState();
const [old, setOld] = useState();
const inputFile = useRef(null);

If you have some kind of codesandbox I can look at, perhaps I could go into more detail about this.