0

I am still a beginner in ReactJS and MERN stack as a whole. The Activate.js code below basically means when the useEffect() hook runs, we will have the jwt token that was taken from the route parameter/url using the {match} props. We decode the token to get the name. Finally, the name and token will be used to save it back in the state - useState({})

Activate.js

import React, { useState, useEffect } from 'react';
import { Link, Redirect, useParams } from 'react-router-dom';
import Layout from '../core/Layout';
import axios from 'axios';
import jwt from 'jsonwebtoken';
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.min.css';

const Activate = ({match}) => {
  const [values, setValues] = useState({
    name: '',
    token: '',
    show: true
  }); // values is an object while setValues is a function

  let paramsToken = useParams(); // useParams replaced match.params.id on react-router-dom 6

  useEffect(() => {
    // let token = match.params.token; // obsolete
    let token = paramsToken;
    let { name } = jwt.decode(token); // destructure to get the name,

    if (token) {
      setValues({...values, name, token});
    }

  }, []);

  const { name, token, show } = values; // destructure

  const clickSubmit = event => {
    // code snippet
  };

  const activationLink = () => (
    <div>
      <h1 className="p-5 text-center">Hey {name}, Ready to activate your account?</h1>
      <button className="btn btn-outline-primary" onClick={clickSubmit}>Activate Account</button>
    </div>
  ); // used parenthesis so we don't use the return keyword

  return (
    <Layout>
      <div className="col-md-6 offset-md-3">
        <ToastContainer />
        {/* {JSON.stringify({name, email, password})}*/} {/* We can use this to know the value in the state */}
        {activationLink()}
      </div>
    </Layout>
  );
};

export default Activate;

package.json

{
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.5",
    "@testing-library/react": "^13.4.0",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^1.3.6",
    "jsonwebtoken": "^9.0.0",
    "react": "^18.2.0",
    "react-dom": "^18.2.0",
    "react-router-dom": "^6.10.0",
    "react-scripts": "5.0.1",
    "react-toastify": "^9.1.2",
    "web-vitals": "^2.1.4"
  }
}

Problem: The problem I am currently facing with jsonwebtoken package is that I am prompted with 2-3 errors and I have indicated those errors below. Please take note that I am following a tutorial and the tutorial's code is for 3 years ago and my latest node.js version and other packages are installed as of March 2023.

Module not found: Error: Can't resolve 'buffer' in 'C:\Users\john\Documents\node-projects\react\mern-ultimate-authentication\mern-auth-client\node_modules\buffer-equal-constant-time'

Module not found: Error: Can't resolve 'crypto' in 'C:\Users\john\Documents\node-projects\react\mern-ultimate-authentication\mern-auth-client\node_modules\jsonwebtoken'

Module not found: Error: Can't resolve 'crypto' in 'C:\Users\john\Documents\node-projects\react\mern-ultimate-authentication\mern-auth-client\node_modules\jsonwebtoken'

BREAKING CHANGE: webpack < 5 used to include polyfills for node.js core modules by default....

Do you know how to solve the issue above? Any help is greatly appreciated. Thanks

redshot
  • 2,930
  • 3
  • 31
  • 68
  • https://stackoverflow.com/questions/64557638/how-to-polyfill-node-core-modules-in-webpack-5 see if this takes anywhere – cmgchess May 04 '23 at 06:48
  • @cmgchess Ah Yes. Thank you for that link. I'm gonna take a look and try to solve the issue on my end too. – redshot May 04 '23 at 06:58

2 Answers2

3

if you want to use jwt.decode() i think you should import the package :

import * as jwt_decode from 'jwt-decode';

or if you want to use jwt.verify() like this :

jwt.verify(yourToken,yourJWTKey,callbackfunction(error,userData){
  // your code here
})
1

I was able to solve the issue by using the jwt-decode package as recommended by another stackoverflow user.

For those who are looking for the correct answer, I have included the updated code below.

Activate.js

import React, { useState, useEffect } from 'react';
import { Link, Redirect, useParams } from 'react-router-dom';
import Layout from '../core/Layout';
import axios from 'axios';
import jwt_decode from "jwt-decode";
import { ToastContainer, toast } from 'react-toastify';
import 'react-toastify/dist/ReactToastify.min.css';

const Activate = ({match}) => {
  const [values, setValues] = useState({
    name: '',
    token: '',
    show: true
  }); // values is an object while setValues is a function

  let paramsToken = useParams(); // useParams replaced match.params.id on react-router-dom 6

  useEffect(() => {
    // let token = match.params.token; // obsolete
    let token = paramsToken;
    // we don't need to type token.name if we destructure it
    let { name } = jwt_decode(JSON.stringify(token)); // jwt_decode() requires the token to be converted into string first

    if (token) {
      setValues({...values, name, token});
    }
  }, []);

  const { name, token, show } = values; // destructure

  const clickSubmit = event => {
    // code snippet
  };

  const activationLink = () => (
    <div>
      <h1 className="p-5 text-center">Hey {name}, Ready to activate your account?</h1>
      <button className="btn btn-outline-primary" onClick={clickSubmit}>Activate Account</button>
    </div>
  ); // used parenthesis so we don't use the return keyword

  return (
    <Layout>
      <div className="col-md-6 offset-md-3">
        <ToastContainer />
        {/* {JSON.stringify({name, email, password})}*/} {/* We can use this to know the value in the state */}
        {activationLink()}
      </div>
    </Layout>
  );
};

export default Activate;
redshot
  • 2,930
  • 3
  • 31
  • 68