Heroku ReactJS 应用程序。 Home 路由功能正常,但是当我尝试另一条路由时,它显示为 404 Not Found

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

我正在尝试为我朋友的学校项目制作一个类似于 sport/tinder 的应用程序。它在我的本地主机上很好地组合在一起,但对他来说,这是在线托管它的要求。不是托管方面的专业人士,但我对 Heroku 有点熟悉。我为我的应用程序使用了客户端和服务器端,因此我构建了客户端并将其放入服务器端文件夹中。该服务器端托管在 Heroku 页面上并显示我的应用程序的首页。但是每当我尝试登录时,它都不起作用,并且我在控制台中收到此错误消息。

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

Heroku 网页是这样说的。

Cannot GET /dashboard

我知道还有很多其他人也有同样的问题。我尝试了很多解决方案,我认为我的路由可能有问题。我是 ReactJS 的新手,所以我真的不知道如何路由,例如工作。而且我更像是一名数据科学家,而不是一名软件工程师,但我总是渴望学习,这就是为什么我抓住机会学习这个新的 'language'。所以说到问题的时候我可能是错的。

这是我用来登录的功能。这个函数在我的客户端,所以我不确定它是否在我构建到我的服务器端时传输。

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)
    }
}

我的index.js服务器的header

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')
})

来自我的 index.js 服务器的注册

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()
}
})

从我的index.js服务器登录

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()
}
})

欢迎任何帮助。我希望我包含了足够的代码示例,如果您需要更多,请回复 ;)

编辑

我的 package.json 服务器目录中的文件。

{
  "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"
},

我的 package.json 客户端目录中的文件。

{
  "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"
},

这是我服务器的配置

/* 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);
});

看看是否可行。我认为您的代码的问题是只发送了主路由,因为只给出了“/”,但不确定。

确保你的目录名指向你的构建目录,因为它现在只指向 public