having a similar issue with req.file being undefined. It looks like the image file is available up until the hook useFormSubmit wraps it in the formData object and sends the formData request to the router/controller.
However even just sending the image using the body, nothing comes through from the hook to the controller. I've included images of the console logs for the status of the data from the component to the controller below, would appreciate any guidance on this:
Things I've tried:
-Sending the form in incognito to avoid cookies or caching
-Sending reviewImage data in the body itself without wrapping it in formData.append
-including the multer middleWare directly in the router and controller
-pulling the image from req.body instead of req.file
CreateReview.tsx
//hooks 
    import {useFormSubmit} from '../../Hooks/useFormSubmit'
//dependencies
import { useForm, SubmitHandler } from "react-hook-form";
export const CreateReview = () => {
const { register, handleSubmit, formState: { errors } } = useForm<ReviewInputs>();
const {createReview, error, isLoading} = useFormSubmit()
const onSubmit: SubmitHandler<ReviewInputs> = async (data) => {
    const userID = user
    const title: string = data.title
    const review: string = data.review
    const artist: string = data.artist
    const author: string = data.author
    const authorBand: string = data.authorBand
    const banner: string = data.banner
    const reviewImage: any = data.reviewImage[0]
    await createReview(title, review, artist, userID, author, authorBand, banner, reviewImage)
    navigate('/adminReviews')
} 
    return (
        <>  
            <Form onSubmit={handleSubmit(onSubmit)} encType="multipart/form-data">
                <Form.Label>Create A Review</Form.Label>
                <Form.Group className="mb-3" controlId="exampleForm.ControlInput1">
                    <Form.Label>Title</Form.Label>
                    <Form.Control type="text" placeholder="Title" {...register('title', {required: true })} {...register} />
                </Form.Group>
                <Form.Group className="mb-3" controlId="exampleForm.ControlInput1">
                    <Form.Label>Artist</Form.Label>
                    <Form.Control type="text" placeholder="Artist" {...register('artist', {required: true })} {...register} />
                </Form.Group>
                <Form.Group className="mb-3" controlId="exampleForm.ControlInput1">
                    <Form.Label>Author</Form.Label>
                    <Form.Control type="text" placeholder="Author" {...register('author', {required: true })} {...register} />
                </Form.Group>
                <Form.Group>
                    <Form.Label>Author Band</Form.Label>
                    <Form.Control type="text" placeholder="Author Band" {...register('authorBand', {required: true })} {...register} />
                </Form.Group>
                <Form.Group>
                    <Form.Label>Upload An Image</Form.Label>
                    <Form.Control type="file" placeholder="Upload" {...register('reviewImage', {required: true })} {...register} />
                </Form.Group>
                <Form.Group>
                    <Form.Label>Banner</Form.Label>
                    <Form.Control type="text" placeholder="Banner" {...register('banner', {required: true })} {...register} />
                </Form.Group>
                <Form.Group>
                    <Form.Label>Review</Form.Label>
                    <Form.Control as="textarea" rows={12} {...register('review', {required: true })} {...register} />
                    <>{errors.review?.message}</>
                </Form.Group>
                <Row>
                    <Col xs={12}>
                        <Button type='submit'>Submit</Button>
                    </Col>
                </Row>
            </Form>
useFormSubmit
export const useFormSubmit = () => {
const {dispatch} = useReviewsContext()
const [error, setError] = useState(null)
const [isLoading, setIsLoading] = useState(false)
const createReview = async (title, review, artist, userID, author, authorBand, banner, reviewImage) => {
    const formData = new FormData();
    formData.append("reviewImage", reviewImage);
    setIsLoading(true)
    setError(null)
        const response = await fetch('http://localhost:8080/api/admin/', {
            method: 'POST',
            headers: {'Content-Type': 'application/json'},
            body: JSON.stringify({title, review, artist, userID, author, authorBand, banner, formData })
        })
        const jsonResponse = await response.json()
        if(!response.ok) {
            setIsLoading(false)
            setError(jsonResponse.error)
        }
        if(response.ok) {
            setIsLoading(false)
            dispatch({type: 'CREATE_REVIEW', payload: jsonResponse})
    }
}
adminMiddleware.js
const multer = require('multer')
const storage = multer.diskStorage({
    destination: (req, file, callback) => {
        callback(null, '../../client/public/images')
    },
    filename: (req, file, callback) => {
        callback(null, file.originalname)
    }
})
const upload = multer({storage: storage})
module.exports = upload;
adminRoutes.js
const express = require('express')
const router = express.Router();
const upload = require('../middleware/adminMiddleware')
//controllers
const { createReview } = require('../controllers/reviewsController')
//CRUD reviews routes
router.post('/', upload.single('reviewImage'), createReview)
module.exports = router;
reviewsController.js
const createReview = async (req, res) => {
const {title, review, artist, userID, author, authorBand, banner} = req.body
const reviewImage = req.file.reviewImage
let emptyFields = []
if(!title) {
    emptyFields.push('title')
}
if(!review) {
    emptyFields.push('review')
}
if(!artist) {
    emptyFields.push('artist')
}
if(!userID) {
    emptyFields.push('userID')
}
if(!author) {
    emptyFields.push('author')
}
if(!authorBand) {
    emptyFields.push('authorBand')
}
if(!banner) {
    emptyFields.push('banner')
}
if(!reviewImage) {
    emptyFields.push('reviewImage')
}
if(emptyFields.length > 0) {
    return res.status(400).json({ error: 'Please fill in all the fields', emptyFields })
}
// add doc to db
try {
    const createdReview = await Review.create({title, review, artist, userID, author, authorBand, banner, reviewImage})
    res.status(200).json(createdReview)
} catch (error) {
    res.status(400).json({error: error.message})
}
}
Error Messages / Console logs
 
