skip to Main Content

I am doing and app with django and react and I want to add authentication. I do it with jwt. Here is the code.

AuthContext.js

export const AuthProvide = ({children}) => {

    const [authToken, setAuthToken] = useState(null)
    const [user, setUser] = useState(null)


    function loginUser(e) {
        e.preventDefault()
        console.log(e)
        axios.post('http://127.0.0.1:8000/api/token/', {
            headers: {
                'Content-type': 'application/json'
            },
            username: e.target.name.value,
            password: e.target.password.value
        })
    }

    let contextData = {
        user: user,
        token: authToken,
        loginUser: loginUser,
    }

    return (
        <AuthContext.Provider value={contextData}>
            {children}
        </AuthContext.Provider>
    )

}

Login.js

import AuthContext from "../context/AuthContext";

const Login = () => {

    const {loginUser} = useContext(AuthContext)

    return (    
        <>
            <Header />
            <form onSubmit={loginUser}>
                <input  type='text' name='username' />
                <input  type='password' name='password' />
                <button onClick={loginUser}>Submit</button>
            </form>
        </>
    )
}

App.js

<BrowserRouter>
          <AuthProvide> 
            <Routes>
              <Route element={<PrivateRoute/>}>
                <Route path='/' element={<Home/>} />
              </Route>
              <Route path='/login' element={<Login/>} />
            </Routes>
          </AuthProvide>
        </BrowserRouter>

But when I run the form I get settle.js:19 Uncaught (in promise) zt {message: 'Request failed with status code 401', name: 'AxiosError', code: 'ERR_BAD_REQUEST', config: {…}, request: XMLHttpRequest, …}

and AuthContext.js:24 Uncaught TypeError: Cannot read properties of undefined (reading ‘value’) in console. In django I did it from django jwt docs

2

Answers


  1. you are not using the right way to send the data inside your loginUser Function. the e.target.username.value will not give you value of username field input (by the way you have used e.target.name.value, which will anyway not give the value)

    1. you have to define the loginUser function inside your Login.js component.
    2. you have to save the username and password fields’ value in a state by using useState hook of react.
    3. Later that, you can share the response you get from the API via authcontext to whichever component within your authcontext if you save it in your shared state
    Login or Signup to reply.
  2. In the AuthContext.js,

    export const AuthProvide = ({children}) => {
    
        const [authToken, setAuthToken] = useState(null)
        const [user, setUser] = useState({
            username: null,
            password: null
        })
    
        function loginUser(e) {
            e.preventDefault()
    
            // Header Config
            const config = {
                headers: {
                  "Content-type": "application/json",
                  Authorization: `Bearer ${authToken}`,
                },
              };
                
            axios.post('http://127.0.0.1:8000/api/token/', // FIXME: You probably want to relook at how to call a POST method or how to name your APIs properly.
                user,
                config
            )
        }
    
        let contextData = {
            user: user,
            setUser: setUser,
            token: authToken,
            loginUser: loginUser,
        }
    
        return (
            <AuthContext.Provider value={contextData}>
                {children}
            </AuthContext.Provider>
        )
    
    }
    
    1. useState() to capture the user input for username and password.

    In the Login.js,

    import AuthContext from "../context/AuthContext";
    
    const Login = () => {
      const { user, setUser, loginUser } = useContext(AuthContext);
    
      return (
        <>
          <Header />
          <form onSubmit={loginUser}>
            <input
              type="text"
              name="username"
              value={user.username}
              onChange={(e) =>
                setUser((prevState) => {
                  return {
                    ...prevState,
                    username: e.target.value,
                  };
                })
              }
            />
            <input
              type="password"
              name="password"
              value={user.password}
              onChange={(e) =>
                setUser((prevState) => {
                  return {
                    ...prevState,
                    password: e.target.value,
                  };
                })
              }
            />
            <button type='submit'>Submit</button>
          </form>
        </>
      );
    };
    
    export default Login;
    
    1. Export the Login component as default.
    2. Use states provided by context to capture and update the respective values.
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search