#javascript #json #reactjs #express
#javascript #json #reactjs #экспресс
Вопрос:
В режиме разработки react и express подключаются идеально, и я могу извлекать данные из серверной части. Но при использовании их в рабочем режиме я получаю статус 200, но не могу получить ответ json от express.
Я получаю эту ошибку:
SyntaxError: JSON.parse: unexpected character at line 1 column 1 of the JSON data
Серверный файл — это:
const express = require('express');
const bodyParser = require("body-parser");
const cors = require("cors");
const path = require("path");
const helmet = require("helmet");
const compression = require("compression");
if(process.env.NODE_ENV !== "production") require('dotenv').config();
const app = express();
//middlewares
app.use(helmet());
app.use(compression());
app.use(cors());
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: true }));
// serve the react app files in production
if(process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "client/build")));
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "client/build", "index.html"))
})
}
//port
const port = process.env.PORT || 5000;
app.listen(port, error => {
if(error) throw error;
console.log(`Backend is running on localhost:${port}`);
});
// connection route
app.get("/express", (req, res) => res.json({express: "YOUR EXPRESS BACKEND IS CONNECTED"}));
Серверный package.json:
{
"name": "",
"version": "1.0.0",
"description": "",
"main": "server.js",
"engines": {
"node": "12.19.0",
"npm": "6.14.8"
},
"scripts": {
"test": "echo "Error: no test specified" amp;amp; exit 1",
"start": "nodemon server.js",
"mainstart": "concurrently --kill-others-on-fail "npm start" "cd client amp;amp; yarn start""
},
"repository": {
"type": "git",
"url": "git https://github.com/g4rry420/armourLine.git"
},
"author": "Gurkiran Singh",
"license": "ISC",
"bugs": {
"url": ""
},
"homepage": "",
"dependencies": {
"body-parser": "^1.19.0",
"compression": "^1.7.4",
"concurrently": "^5.3.0",
"cors": "^2.8.5",
"dotenv": "^8.2.0",
"express": "^4.17.1",
"helmet": "^4.2.0",
"nodemon": "^2.0.6",
"path": "^0.12.7"
}
}
Интерфейс App.js
import React,{ useEffect, useState } from 'react';
import { Route, Switch } from "react-router-dom"
import './App.css';
import Header from "./components/header/header.component"
import ProductItem from './components/product-item/product-item.component';
import Homepage from './pages/homepage.component';
import ProductForm from "./components/product-form/product-form.component";
function App() {
const [backendData, setBackendData] = useState("No Fetching")
useEffect(() => {
callBackedApi()
.then(res => setBackendData(res.express))
.catch(err => console.log(err))
}, [])
async function callBackedApi(){
const response = await fetch("/express", {
headers: {
'Content-Type': 'application/json',
},
})
const body = await response.json();
if(response.status !== 200){
throw Error(body.message)
}
return body;
}
return (
<div className="App">
{backendData}
<Header />
<div>
<Switch>
<Route exact path="/" component={Homepage} />
<Route path="/product" component={ProductItem} />
<Route path="/product-form" component={ProductForm} />
</Switch>
</div>
</div>
);
}
export default App;
Внешний интерфейс package.json
{
"name": "armourline",
"version": "0.1.0",
"private": true,
"proxy": "http://localhost:5000",
"dependencies": {
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"bootstrap": "^4.5.2",
"react": "^16.13.1",
"react-bootstrap": "^1.3.0",
"react-dom": "^16.13.1",
"react-icons": "^3.11.0",
"react-router-dom": "^5.2.0",
"react-scripts": "3.4.3",
"react-slick": "^0.27.13"
},
"scripts": {
"start": "react-scripts start",
"build": "react-scripts build",
"test": "react-scripts test",
"eject": "react-scripts eject"
},
"eslintConfig": {
"extends": "react-app"
},
"browserslist": {
"production": [
">0.2%",
"not dead",
"not op_mini all"
],
"development": [
"last 1 chrome version",
"last 1 firefox version",
"last 1 safari version"
]
}
}
Ответ №1:
У вас проблема с упорядочением маршрута.
В рабочей среде этот код активен:
// serve the react app files in production
if(process.env.NODE_ENV === "production") {
app.use(express.static(path.join(__dirname, "client/build")));
app.get("*", (req, res) => {
res.sendFile(path.join(__dirname, "client/build", "index.html"))
})
}
Который помещает app.get("*", ...)
маршрут ПЕРЕД вашим app.get("/express", ...)
маршрутом, поэтому * route перехватит запрос и отправит его в формате HTML, который не будет анализироваться как JSON. Порядок ваших маршрутов имеет значение, когда они могут конфликтовать.
Переместите свой app.get("/express", ...)
маршрут ПЕРЕД своим app.get("*", ...)
маршрутом, фактически, маршрут *, вероятно, должен быть последним, чтобы все индивидуально указанные маршруты получили шанс перехватить запрос до того, как это сделает маршрут *. Лично я сам не использую * routes из-за некоторых проблем, которые они могут вызвать.
Комментарии:
1. а что, если я захочу добавить какие-либо дополнительные маршруты, должен ли я также добавить их два раза, один в рабочей среде и один в разработке?
2. @GurkiranSingh — Я никогда не предлагал вам добавлять маршрут два раза. Я предположил, что вам нужно добавлять маршруты в правильном порядке, когда у вас есть перекрывающиеся определения маршрутов.
3. @GurkiranSingh — Чтобы мы могли помочь вам в дальнейшем, нам нужно больше информации, которая «все еще не работает». Вам нужно посмотреть на фактический ответ, который вы получаете с
console.log()
помощью отладчика, и посмотреть, что именно это такое, и поделиться этим с нами.4. @GurkiranSingh — Это ответило на ваш вопрос? Если это так, вы можете сообщить об этом сообществу, щелкнув галочку слева от ответа, и это также принесет вам несколько очков репутации за соблюдение надлежащей процедуры.