1

I've been trying to turn my authentication form submit to a reducer for 3 days and ive searched and read everything i could find and i found a partial answer for handle change but cant figure out how to do the handle submit function, ive seen how other's have done it but none of them is similar to mine, please guide me how to find my solution, here is my code before reducers:

import React, {createContext, useState} from 'react';
import axios from "axios";

export const SignInContext = createContext();

const SignInContextProvider = (props) => {

    const [formData, setFormData] = useState({

        email: '',
        password: '',

        error: '',
        success: false
    })

    const {email, password, error, success} = formData;


    const clickSubmit = async event => {
        event.preventDefault()

        setFormData({...formData})

        await axios.interceptors.response.use((response) => {
            // do something with the response data
            // console.log('Response was received');

            return response;
        }, error => {
            // handle the response error
            // console.log(error.response.data.message)
            setFormData({...formData, error: error.response.data.message, success: false})
            return Promise.reject(error.response.data.message);
        });


        await axios({
            method: 'post',
            url: 'http://localhost:5001/api/user/signin',
            data: {email, password}
        })
            .then((response) => {
                    console.log(response);
                    if (response.data.status===200) {
                        setFormData({...formData, success: response.data.message});
                        localStorage.setItem('myData', response.data.token);
                        localStorage.setItem('type', response.data.type);
                    }
                    else {
                        setFormData({...formData, error: response.data.message, success: false});
                    }
                },
                (error) => (
                    console.log(error),
                        setFormData({...formData, error: error, success: false})
                ));

    }

    const handleChange = name => event => {
        setFormData({...formData, error: false, [name]: event.target.value})
    };

    const showError = () => (
        <div>
            <div className="alert alert-danger text-center" style={{display: error ? '' : 'none'}}>
                {error}
            </div>
        </div>
    );

    const showSuccess = () => (
        <div className="alert alert-success text-center" style={{display: formData.success ? '' : 'none'}}>
            {success}
        </div>
    );

    return (
        <SignInContext.Provider value={{ ...formData, clickSubmit, handleChange, showError, showSuccess }}>
            {props.children}
        </SignInContext.Provider>
    );
};

export default SignInContextProvider;

this is the handle change reducer:

export const signInReducer = (state, {field, value}) => {
    return [...state, {
        [field]: value
    }]
}

here is my handle change method for the reducer:

const initialState = {

    email: '',
    password: '',

    error: '',
    success: false
};

const {email, password, error, success} = signInData;

const handleChange = e => {
    dispatch({ field: e.target.name, value: e.target.value })
}

Im not looking for a hand out solution, but im tired of not finding a way for 3 days, i need to move on, please guide me

Ali Najdi
  • 83
  • 1
  • 1
  • 9

1 Answers1

0

Thanks to @Tim Ermilov

import React, { createContext, useReducer } from 'react';
import axios from 'axios';

export const SignInContext = createContext();

const initialState = {
  formData: {
    email: '',
    password: '',
  },
  error: '',
  success: false
};

function reducer(state, action) {
  switch (action.type) {
    case 'save':
      return { ...action.payload };
    case 'error':
      // TODO: do something with error
      return { ...action.payload };
    case 'success':
        return { ...action.payload };
    case 'change':
      return { ...state, formData: action.payload.formData };
    default:
      throw new Error();
  }
}

const SignInContextProvider = props => {
  const [state, dispatch] = useReducer(reducer, initialState);

  const { email, password, error, success } = state;

  const clickSubmit = async event => {
    event.preventDefault();

    dispatch({ type: 'save', payload: formData });

    await axios.interceptors.response.use(
      response => {
        // do something with the response data
        // console.log('Response was received');

        return response;
      },
      error => {
        // handle the response error
        // console.log(error.response.data.message)
        dispatch({
          type: 'error',
          payload: {
            formData,
            error: error.response.data.message,
            success: false
          }
        });
        return Promise.reject(error.response.data.message);
      }
    );

    await axios({
      method: 'post',
      url: 'http://localhost:5001/api/user/signin',
      data: { email, password }
    }).then(
      response => {
        console.log(response);
        if (response.data.status === 200) {
          dispatch({type: 'success', payload: {...formData, success: response.data.message }});
          localStorage.setItem('myData', response.data.token);
          localStorage.setItem('type', response.data.type);
        } else {
          dispatch({
            type: 'error',
            payload: {
            formData,
            error: response.data.message,
            success: false
            }
          });
        }
      },
      error => (
        console.log(error),
        dispatch({type: 'error', payload: { formData, error: error, success: false } })
      )
    );
  };

  const handleChange = name => event => {
    dispatch({type: 'change', payload: formData }});
  };

  const showError = () => (
    <div>
      <div
        className="alert alert-danger text-center"
        style={{ display: error ? '' : 'none' }}
      >
        {error}
      </div>
    </div>
  );

  const showSuccess = () => (
    <div
      className="alert alert-success text-center"
      style={{ display: formData.success ? '' : 'none' }}
    >
      {success}
    </div>
  );

  return (
    <SignInContext.Provider
      value={{ ...formData, clickSubmit, handleChange, showError, showSuccess }}
    >
      {props.children}
    </SignInContext.Provider>
  );
};

export default SignInContextProvider;
Ali Najdi
  • 83
  • 1
  • 1
  • 9