Stephen Aranda
Stephen Aranda

Reputation: 183

How can I add my Axio post on submit of my upload form when I am using a custom hook for form validation?

I am trying to allow a user to submit an image file (.jpeg, .png) and a title for that image (text) to my backend API but am having some issues on how to go about it. The reason is because I am using a custom hook named useForm in my upload component so that it can pull the validation functions from the file. But I have a function called postUserImage in my upload component which reads the image file and the title that is inputted by checking the state. How can I use the code that is in postUserImage if my onSubmit is already using the form validation submitHandler? I hope that makes sense, if anyone can help with this it would be great. Update: Here is a sandbox with code, still haven't figure it out. https://codesandbox.io/s/flamboyant-cray-izcj6z?file=/src/App.js

Upload.jsx:

mport {useEffect, useState} from 'react';
import {} from 'react-router-dom';
import {useDispatch, useSelector} from 'react-redux';
import axios from 'axios';
import {clearMessage} from '../../slices/messages';
import authHeader from '../../services/auth-header';
import useForm from '../../hooks/useForm';
const API_URL = 'http://localhost:8080/api/posts';

function Uploads(onUpload) {
    const {user: currentUser} = useSelector((state) => state.auth);
    const [file, setFile] = useState();
    const [title, setTitle] = useState();
    const [description, setDescription] = useState('');
    const [loading, setLoading] = useState(false);
    const [content, setContent] = useState('');
    const [preview, setPreview] = useState(null);

    useEffect(() => {}, []);

    const onAddImage = (file) => {
        window.URL.revokeObjectURL(preview);
        if (!file) return;
        setPreview(window.URL.createObjectURL(file));
    };
    const postUserImage = async (event) => {
        event.preventDefault();

        const formData = new FormData();
        formData.append('file', file);
        formData.append('title', title);

        const result = await axios.post('/post/upload', formData, {
            headers: {...authHeader(), 'Content-Type': 'multipart/form-data'},
        });
        console.log(result.data);
    };

    //Custom hook call
    // const {handleChange, values, errors, handleSubmit} = useForm(postUserImage);
    const initialState = {title: ''};
    const validations = [
        ({title}) => isRequired(title) || {title: 'Title is required'},
    ];
    const {values, isValid, errors, changeHandler, submitHandler, touched} =
        useForm(initialState, validations, onUpload);

    return (
        <div className='page'>
            <div className='upload-card'>
                <div id='preview'>
                    <img
                        src={preview || require('../../assets/user-solid.jpeg')}
                        id='image'
                        alt='Thumbnail'
                        className='user-post'
                    />
                </div>
            </div>
            <div className='upload-container'>
                <div className='post-form-container'>
                    <p id='upload-form-label'>Hello, feel free to post an image!</p>
                    <form
                        // onSubmit={'return Validate(this);'}

                        onSubmit={submitHandler}
                        className='upload-form'
                    >
                        <div className='panel'>
                            <div className='button_outer'>
                                <div className='btn_upload'>
                                    <input
                                        filename={file}
                                        onChange={(e) => onAddImage(e.target.files[0])}
                                        type='file'
                                        accept='.jpeg,.svg,.gif,.png'
                                        id='image-selection-btn'
                                    ></input>
                                    Choose your Art
                                </div>
                            </div>
                        </div>
                        <input
                            name='title'
                            type='text'
                            className='form-control'
                            placeholder='Enter Title'
                            id='cred-input'
                            required
                            value={values.title}
                            onChange={changeHandler}
                        />

                        {touched.title && errors.title && (
                            <p className='error'>{errors.title}</p>
                        )}

                        <button type='submit' id='post-upload-btn' disabled={isValid}>
                            Upload Image
                        </button>
                    </form>
                </div>
            </div>
        </div>
    );
    function isRequired(value) {
        return value != null && value.trim().length > 0;
    }

    function isSame(value1, value2) {
        return value1 === value2;
    }
}

export default Uploads;

useForm.js:

import React, {useState} from 'react';
import {omit} from 'lodash';

function useForm(initialState = {}, validations = [], onSubmit = () => {}) {
    // Add the 'onSubmit' argument
    const {isValid: initialIsValid, errors: initialErrors} = validate(
        validations,
        initialState
    );
    const [values, setValues] = useState(initialState);
    const [errors, setErrors] = useState(initialErrors);
    const [isValid, setValid] = useState(initialIsValid);
    const [touched, setTouched] = useState({});
    const [file, setFile] = useState();
    const [title, setTitle] = useState();
    const changeHandler = (event) => {
        const newValues = {...values, [event.target.name]: event.target.value};
        const {isValid, errors} = validate(validations, newValues);
        setValues(newValues);
        setValid(isValid);
        setErrors(errors);
        setTouched({...touched, [event.target.name]: true});
    };
    // Add this
    const submitHandler = (event) => {
        event.preventDefault();
        onSubmit(values);
    };
    return {values, changeHandler, isValid, errors, touched, submitHandler}; // Add 'submitHandler'
}

function validate(validations, values) {
    const errors = validations
        .map((validation) => validation(values))
        .filter((validation) => typeof validation === 'object');
    return {
        isValid: errors.length === 0,
        errors: errors.reduce((errors, error) => ({...errors, ...error}), {}),
    };
}

export default useForm;

Upvotes: 0

Views: 87

Answers (1)

Erdem &#220;n
Erdem &#220;n

Reputation: 228

sample

const formData = new FormData();
formData.append('file', file);
formData.append('title', title);

const config = {
  url: 'url',
  data: formData,
  headers: {
    ...formData.getHeaders() // <- formdata header.
  }
}

axios.request(config)

Upvotes: 1

Related Questions