Après avoir déployé mon application mern sur Heroku, la requête GET
sur la page d'accueil ('http://localhost:8000/post/')
renvoie maintenant index.html
au lieu des json data
de la requête. J'obtiens un code d' 200 status
mais la réponse est html
. Cependant, cela fonctionne bien localement.
Toutes les autres demandes fonctionnent sauf celle-ci. Chaque fois que je pense que je l'ai corrigé, Heroku affiche les données json au lieu de l'interface utilisateur sur cette même route. Je suppose que ces problèmes sont liés.
Comment puis-je résoudre ça? Merci!
route / controller - liste des messages
class ListPosts extends React.Component { state = { title: '', body: '', date: '', posts: [] } componentDidMount = () => { this.getPosts() } getPosts = () => { axios.get(`${API}/post`) .then((response) => { const data = response.data this.setState({posts: [data]}) console.log(data) }) .catch((error) => { console.log(error) }) } displayPosts = (posts) => { if (!posts.length) return null; posts.map((post, index) => ( <div key={index}> ... </div> )) } render() { return ( <div> {this.displayPosts(this.state.posts)} </div> ) } } export default ListPosts
server.js
require("dotenv").config(); // import routes ... const app = express(); // connect db - first arg is url (specified in .env) const url = process.env.MONGODB_URI mongoose.connect(url, { useNewUrlParser: true, useCreateIndex: true, useUnifiedTopology: true, useFindAndModify: false, }); mongoose.connection .once("open", function () { console.log("DB Connected!"); }) .on("error", function (error) { console.log("Error is: ", error); }); // middlewares app.use(function(req, res, next) { res.header("Access-Control-Allow-Origin", '*'); res.header("Access-Control-Allow-Credentials", true); res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE,OPTIONS'); res.header("Access-Control-Allow-Headers", 'Origin,X-Requested-With,Content-Type,Accept,content-type,application/json'); next(); }); // middleware ... // app.use(express.static(path.join(__dirname, './client/build'))) app.use(authRoutes); app.use(userRoutes); app.use('/post', postRoutes); if (process.env.NODE_ENV === "production") { app.use(express.static("client/build")); } app.get("/*", function (req, res) { res.sendFile(path.join(__dirname, "./client/build/index.html")); }); const port = process.env.PORT || 80; app.listen(port, () => { console.log(`Server is running on port ${port}`); });
ListPosts.js
router.get('/', (list)) exports.list = (req, res) => { const sort = { title: 1 }; Post.find() .sort(sort) .then((posts) => res.json(posts)) .catch((err) => res.status(400).json("Error: " + err)); };
4 Réponses :
if (process.env.NODE_ENV === "production") { app.use(express.static("client/build")); } app.get("/*", function (req, res) { res.sendFile(path.join(__dirname, "./client/build/index.html")); }); .... app.use(authRoutes); app.use(userRoutes); app.use(postRoutes);
Merci pour votre réponse. J'ai essayé cela mais malheureusement, il répond toujours avec index.html. @NattawutPornpetcharat
module.exports = routeur; Avez-vous mis à jour comme ça sur l'itinéraire? Pouvez-vous publier plus de code sur postRoutes?
Oui, j'avais déjà une déclaration d'exportation dans le fichier d'itinéraire. Je ne l'avais simplement pas ajouté à mon code sur SO. Tous mes autres itinéraires fonctionnent bien, c'est juste celui-ci qui renvoie du html. @NattawutPornpetcharat
Dans votre implémentation actuelle, vous avez 2 app.get pour le même chemin -> '/' Donc, express répond avec le premier. Ce qui est actuellement:
router.post('/' ...) // instead of router.get('/'...)
Vous pouvez soit spécifier un chemin différent
app.use(authRoutes); app.use(userRoutes); app.use(postRoutes); app.get("/*", function (req, res) { res.sendFile(path.join(__dirname, "./client/build/index.html")); });
ou réorganisez la séquence.
app.use("/post", postRoutes);
ou changer de contrôleur
app.get("/*", function (req, res) { res.sendFile(path.join(__dirname, "./client/build/index.html")); });
Vous devez spécifier l'URL des routes ou éviter deux 'app.get' pour la même route. Si vous le souhaitez, vous pouvez également changer le contrôleur de 'app.get' à 'app.post' et express les jugera différents. Mais, si les deux sont app.get pour la même route, le premier enverra la réponse et le second ne sera jamais appelé.
Ce que vous pouvez faire, c'est d'abord essayer de réorganiser la séquence. Si cela fonctionne et que c'est effectivement le problème, ne vous en tenez pas à cela comme solution. C'est la mauvaise façon de procéder. Au lieu de cela, donnez à vos routes une URL différente ou changez le contrôleur de 'app.get' à 'app.post'
Votre requête 'http://localhost:8000/'
correspond à deux gestionnaires de route
app.use('api/auth', authRoutes); app.use('api/post', postRoutes); app.use('api/user', userRoutes);
router.get('/', (list))
Puisque votre route de construction client est placée au-dessus de la route de liste , elle renverra toujours l'index.html car la priorité est importante dans express lors de la définition des routes.
Une bonne pratique et une solution consiste à toujours différencier vos routes API des routes statiques en ajoutant /api
avant toutes les routes comme ci-dessous
app.get("/*", function (req, res) { res.sendFile(path.join(__dirname, "./client/build/index.html")); });
Comme certaines des réponses ont déjà mentionné la séparation de votre API et des routes client et ont trouvé le problème exact, je voudrais simplement ajouter quelques recommandations basées sur mon expérience avec la diffusion de votre application React en utilisant express
. (L'astuce consiste également à ajouter le contrôle de version)
app.use('/api/v1/auth', authRoutes); app.use('/api/v1/user', userRoutes); app.use('/api/v1/post', postRoutes); if (process.env.NODE_ENV === 'production') { app.use(express.static(path.join(__dirname, "client/build"))); app.get("/*", (_, res) => { res.sendFile(path.join(__dirname, "client/build", "index.html")); }); }
Où est votre API? On dirait que vous envoyez une requête
axios
au même serveur qui sert le code React.L'API est sur localhost: 8000 et donc l'application react est sur le port 8001 @Dilshan
Pouvez-vous ajouter l'objet de requête
axios