Home > Blockchain >  Heroku ReactJS app. Home route is functional, but when I try another route it shows up as 404 Not Fo
Heroku ReactJS app. Home route is functional, but when I try another route it shows up as 404 Not Fo

Time:05-16

I'm trying to make a sport/tinder like app for a school project from a friend of mine. It came together well on my localhost, but for him it was a requirement to host it online. Not really a professional in hosting, but I was a bit familiar with Heroku. I used a client and a server side for my application, so I build the client side and put it into the server side folder. This server side is hosted on the Heroku page and shows the front page of my application. But whenever I try to login, it won't work and I get this error message in my console.

​GET https://[app].herokuapp.com/dashboard 404 (Not Found)

And the Heroku webpage says this.

Cannot GET /dashboard

I know there are a lot of other people with the same issue. I tried many solutions and I think something might be wrong with my routing. I'm very new to ReactJS so I don't really know how the routing e.g. work. And I'm more like a Data Scientist then a Software Engineer, but I'm always eager to learn that's why I took the oppurtunity to learn this new 'language'. So I might be wrong when it comes to the problem.

This is the function I use to login with. This function is on my client side so I'm not sure if it transfers when I build to my server side.

const handleSubmit = async (e) => {
    e.preventDefault()
    try {
        if( isSignUp && ( password !== confirmPassword)) {
            setError('Passwords need to match!')
            return
        }

        const response = await axios.post(`https://[app].herokuapp.com/${isSignUp ? 'signup' : 'login'}`, { email, password })

        setCookie('AuthToken', response.data.token)
        setCookie('UserId', response.data.userId)

        const success = response.status === 201

        if (success && isSignUp) navigate('/onboarding')
        if (success && !isSignUp) navigate('/dashboard')

        window.location.reload()

    } catch (error) {
        console.log(error)
    }
}

The header of my index.js server

const PORT = process.env.PORT || 8000
const express = require('express')
const {MongoClient} = require('mongodb')
const {v1: uuidv4} = require('uuid')
const jwt = require('jsonwebtoken')
const cors = require('cors')
const bcrypt = require('bcrypt')
require('dotenv').config()

const uri = process.env.URI

const app = express()
app.use(cors())
app.use(express.json())
app.use(express.static(__dirname   "/public"));

app.get('/', (req, res) => {
    res.json('Hello to my app')
})

The signup from my index.js server

app.post('/signup', async (req, res) => {
const client = new MongoClient(uri)
const {email, password} = req.body

const generateUserId = uuidv4()
const hashedPassword = await bcrypt.hash(password, 10)

try {
    await client.connect()
    const database = client.db('app-data')
    const users = database.collection('users')

    const existingUser = await users.findOne({email})

    if (existingUser) {
        return res.status((409).send('User already exists. Please login'))
    }

    const sanitizedEmail = email.toLowerCase()

    const data = {
        user_id: generateUserId,
        email: sanitizedEmail,
        hashed_password: hashedPassword
    }

    const insertedUser = await users.insertOne(data)

    const token = jwt.sign(insertedUser, sanitizedEmail, {
        expiresIn: 60 * 24,
    })

    res.status(201).json({token, userId: generateUserId})
} catch (err) {
    console.log(err)
} finally {
    await client.close()
}
})

The login from my index.js server

app.post('/login', async (req, res) => {
const client = new MongoClient(uri)
const {email, password} = req.body

try {
    await client.connect()
    const database = client.db('app-data')
    const users = database.collection('users')

    const user = await users.findOne({email})

    const correctPassword = await bcrypt.compare(password, user.hashed_password)

    if (user && correctPassword) {
        const token = jwt.sign(user, email, {
            expiresIn: 60 * 24
        })
        res.status(201).json({token, userId: user.user_id})
    }
    res.status(400).send('Invalid Credentials')
} catch (err) {
    console.log(err)
} finally {
    await client.close()
}
})

Any help is welcome. I hope I included enough code examples, reply if you need more ;)

EDIT

My package.json file from the server directory.

{
  "name": "server",
  "version": "1.0.0",
  "description": "",
  "main": "index.js",
  "scripts": {
    "start": "node index.js",
    "start:backend": "nodemon index.js",
    "test": "echo \"Error: no test specified\" && exit 1"
},

My package.json file from the client directory.

{
  "name": "funfit",
  "homepage": "https://[app].herokuapp.com/",
  "version": "0.1.0",
  "private": true,
  "dependencies": {
    "@testing-library/jest-dom": "^5.16.2",
    "@testing-library/react": "^12.1.4",
    "@testing-library/user-event": "^13.5.0",
    "axios": "^0.26.1",
    "react": "^17.0.2",
    "react-cookie": "^4.1.1",
    "react-dom": "^17.0.2",
    "react-router-dom": "^6.2.2",
    "react-scripts": "5.0.0",
    "react-tinder-card": "^1.4.5",
    "web-vitals": "^2.1.4"
  },
  "scripts": {
    "predeploy": "npm run build",
    "deploy": "gh-pages -d build",
    "start:frontend": "./node_modules/.bin/react-scripts start",
    "build": "./node_modules/.bin/react-scripts build",
    "test": "./node_modules/.bin/react-scripts test",
    "eject": "./node_modules/.bin/react-scripts eject"
},

CodePudding user response:

This is my server's configurations

/* import */
const path = require("path");

app.use(express.static(__dirname   "/../client/build"));


app.get("*", (req, res) => {
  // send index.html
  let indexPath = path.join(__dirname, "/../client/build/index.html")
  res.sendFile(indexPath);
});

See if that works. I think the issue with your code is only home route gets sent since only "/" given, but not sure.

Make sure your dirname points to your build directory I see as it is right now it points to public only

  • Related