Home > Back-end >  Function not being called from props React
Function not being called from props React

Time:11-30

for some reason function, that is passed into a functional component never gets called. The onSubmit function gets called but then it never calls login(email, password). Basically I pass the login function from auth.tsx into the Login component and then I try to call the function in onSubmit function inside Login component but the function never gets called. I tried adding console.log inside the login function but nothing gets returned in console nor I see any API requests in backend console. Here is my code:

App.tsx

import React, { FunctionComponent }  from 'react'
import Home from './pages/Home/Home'
import { BrowserRouter as Router, Routes, Route } from 'react-router-dom'
import { Activate, Login, Signup, ResetPassword,  ResetPasswordConfirm } from './pages/Account'
import Layout from './components/Layout'
import { login } from "./actions/auth";

import { Provider } from 'react-redux'
import store from './store'

const App: FunctionComponent = () => (
  <Provider store={store}>
    <Router>
      <Routes>
        <Route path="/" element={<Home />} />
        <Route path="/login" element={<Login login={login}/>} />
        <Route path="/signup" element={<Signup />} />
        <Route path="/reset-password" element={<ResetPassword />} />
        <Route path="/password/reset/confirm/:uid/:token" element={<ResetPasswordConfirm />} />
        <Route path="/activate/:uid/:token" element={<Activate />} />
      </Routes>
    </Router>
  </Provider>
)


export default App

Login.tsx

import { FunctionComponent, useState } from "react";
import { Link, redirect } from "react-router-dom";
import { connect } from "react-redux";


interface IFormData {
    email: string;
    password: string;
}

interface ILogin {
    login: (email: string, password: string) => void;
}

const Login: FunctionComponent<ILogin> = ({ login }) => {
    const [formData, setFormData] = useState<IFormData>({
        email: "",
        password: "",
    });

    const { email, password } = formData;

    const onChange = (e: React.ChangeEvent<HTMLInputElement>) => setFormData({
        ...formData,
        [e.target.name]: e.target.value,
    })

    const onSubmit = async (e: React.FormEvent<HTMLFormElement>) => {
        e.preventDefault();
        login(email, password)
    }

    return (
        <div>
            <h1>Sign In</h1>
            <p>Sign into your account</p>
            <form onSubmit={e => onSubmit(e)}>
                <div>
                    <input 
                        type="email"
                        placeholder="email"
                        name="email"
                        value={email}
                        onChange={e => onChange(e)}
                        required
                    />
                </div>
                <div>
                    <input 
                        type="password"
                        placeholder="password"
                        name="password"
                        value={password}
                        onChange={e => onChange(e)}
                        minLength={6}
                        required
                    />
                </div>
                <button type="submit" >
                    Login
                </button>
            </form>
            <p>
                Don't have an account? <Link to="/signup">Sign Up</Link>
            </p>
            <p>
                Forgot your password? <Link to="/reset-password">Reset Password</Link>
            </p>
        </div>
    )
}

export default connect(null, { })(Login);

auth.tsx

import { 
    LOGIN_SUCCESS,
    LOGIN_FAIL,
    USER_LOAD_SUCCESS,
    USER_LOAD_FAIL
} from './types';

import axios from 'axios';

export const load_user = () => async (dispatch: any) => {
    if (localStorage.getItem('access')) {
        const config = {
            headers: {
                'Content-Type': 'application/json',
                'Authorization': `JWT ${localStorage.getItem('access')}`,
                'Accept': 'application/json'
            }
        };
    try {
        const res = await axios.get(`${process.env.REACT_APP_API_URL}/api/users/me/`, config);
        dispatch({
            type: USER_LOAD_SUCCESS,
            payload: res.data
        });
    } catch (err) {
        dispatch({
            type: USER_LOAD_FAIL
        });
    }
    } else {
        dispatch({
            type: USER_LOAD_FAIL
        });
    }
};

export const login = (username: string, password: string) => async (dispatch: any) => {
    const config = {
        headers: {
            'Content-Type': 'application/json'
        }
    }

    const body = JSON.stringify({ username, password });
    console.log("yay")
    try {
        const res = await axios.post(`${process.env.REACT_APP_API_URL}/api/jwt/create/`, body, config);

        dispatch({
            type: LOGIN_SUCCESS,
            payload: res.data
        });

        dispatch(load_user());
    } catch (err) {
        dispatch({
            type: LOGIN_FAIL
        });
    }
}

CodePudding user response:

This is because your login function is a curried function and hence if you wish to execute it directly you would need to do login(email, password)()

Your login function (defined in auth.tsx) seems to look like a thunk/saga in which case you should be dispatching the login function call from the Login component (defined in Login.tsx) using the MapDispatchToProps callback for the connect HOC.

  • Related