NextJS images not loading - reactjs

In my root project I have a /public holder set up with a "home.jpg" and "home-placeholder.jpg" image files.
Inside my /pages/index.js file I have a component that takes in two images:
function Page() {
return (
<>
<Head title="Home" />
<Home>
<Right
alt="home-image"
image="./home.jpg"
placeholder="./home-placeholder.jpg"
/>
</Home>
</>
);
}
I cannot get those images to display in my dev server, I always get: Cannot GET /home.jpg.
I've tried:
using next-images and importing the images
building and deploying on my production server
changing name of public folder to /static/
The images are correctly loading inside the output path /.next/static/images/

You are using custom Express Server and you are missing Next app requestHandler:
import * as Routes from "~/src/routes";
import express from "express";
import next from "next";
const dev = process.env.NODE_ENV !== "production";
const port = process.env.PORT || 8000;
const app = next({ dev, quiet: false });
const handle = app.getRequestHandler(); // <----
app.prepare().then(() => {
const server = express();
server.get("/", async (req, res) => {
return await Routes.signIn(req, res, app);
});
server.all("*", (req, res) => { // <----
return handle(req, res);
});
server.listen(port, (err) => {
if (err) throw err;
console.log(`Server running on http://localhost:${port}`);
});
});
Check out this Custom Express Server example by Next.js.

Related

unexpected token in json at position 0 reactjs mongodb

///component
function Home() {
const [show, setShow]= useState([{name:'', info:'', airingDate:'', poster:''}])
useEffect(()=>{
fetch("/home")
//.then(res=> res.json())
.then(res => res.text())
.then(text => console.log(text))
})
return (
<div>
{show.map(a=>
<div>
<h2>{a.title}</h2>
</div>
)}
</div>
)
/////index.js
const TvShows = require("./models/TvShows");
const express = require("express");
const app = express();
const mongoose= require("mongoose")
const dotenv= require("dotenv");
const authRoute = require("./routes/auth");
const { application } = require("express");
const userRoute = require("./routes/users");
const commentRoute = require("./routes/comments");
const tvshowsRoute = require("./routes/tvshows");
const cors = require("cors");
app.use(cors());
console.log(".");
dotenv.config();
app.use(express.json());
mongoose.connect(process.env.MONGO_URL,{
useCreateIndex: true,
useNewUrlParser: true,
useUnifiedTopology: true,
}).then(console.log("connected to mongoDB"));
app.use("/auth", authRoute);
app.use("/users", userRoute);
app.use("/comments", commentRoute);
app.post("/api/home", tvshowsRoute);
app.use("/api/home", tvshowsRoute);
/*
app.get('/api/home', (req,res)=>{
TvShows.find().then((result)=>{
res.send(result);
})
})
*/
/*
app.use("/",(req,res)=>{
console.log("main url")
})*/
app.listen("3001",()=>{
console.log("backend running");
})
//////route
const router = require("express").Router();
const TvShows = require("../models/TvShows");
router.post("/api/home", async (req, res) => {
console.log("here")
try{
const newTvShow = new TvShows({
title: req.body.title,
poster: req.body.poster,
info: req.body.info
});
const savedTvShows = await newTvShow.save();
res.status(200).json(savedTvShows);
}catch (err) {
res.status(500).json(err);
}
}
);
router.route("/api/home").get((req, res)=>{
TvShows.find()
.then(foundShows=> res.json(foundShows))
})
module.exports = router;
when I change res.json with res.text I see my index.html page on console not the data I want to fetch from mongodb. This error is probably because I didn't use /api/ on root url but I couldn't figure it out where I should write it. I tried but didn't work. It would be so good if someone could've helped. Thank you so much.
Indeed, you are fetching the /home page of your front-end app.
Assuming the api is on a different server, you would need to call the address of that server.
If you have a set up locally with a nodejs server and a react app running separately, you should have them run on two different ports.
If you have react app on http://localhost:3000 (default), then change your api to listen on 3001, then in your react code above, you can use the full uri
http://localhost:3001/api/home
in your fetch call.
I'm making a lot of assumptions about how you have this set up, based on my own experience of local development for similar problems.

NextJs - React component methods get called twice per request

I'm experimenting with NextJs Custom Server using Express. And i noticed that on every request, getInitialProps gets called twice. When trying to find out what the problem is i stumbled upon React.Strictmode being the reason for that since it calls certain class methods and constructor twice to help debug. When setting it to false, the getInitialProps method gets called three times. NextJs "pages" folder routing is disabled.
To be mentioned that render() gets called twice or three times too.
My server.js :
require('dotenv').config();
const express = require('express');
const next = require('next');
const dev = process.env.NODE_ENV !== 'production';
const mongoose = require('mongoose');
const app = next({ dev });
mongoose.connect(process.env.DB_URI)
.then(()=>{
console.log('>Succesfully connected to the database');
app.prepare()
.then(() => {
const server = express();
server.listen(3000, (req, res) =>{
console.log('>Listening on port 3000');
});
server.get('*', (req, res)=>{
app.render(req, res, '/index', {something:true});
})
})
.catch((ex) => {
console.error(ex.stack);
process.exit(1);
})
})
.catch(e=>{
console.log('<!>Error connecting to database: \n' + e);
});
and my GetInitialProps:
static async getInitialProps(ctx){
console.log({...ctx.query});
console.log('once');
return {props:{...ctx.query}};
}
Console when Strictmode on:
{ something: true }
once
{ something: true }
once
Console when Strictmode off:
{ something: true }
once
{ something: true }
once
{ something: true }
once

How to make url alias in next js and express for posts or users that you get their data by id?

I would like to redirect a request url with the blog/:id: formatting for a more user friendly url like the blog/blogtitle and category that i get from a a json api.
I manage to solve this partialy by res.redirect after the app.render in my server.js.
My problem is that next.js initially searches for the url alias as a page component in my pages folder and thus i get a status code of 404 before my res.redirect.
Any ideas?
You can redirect to the specific page for each request:
(see commands on server.js)
server.js
const express = require('express')
const next = require('next')
const port = parseInt(process.env.PORT, 10) || 3000
const dev = process.env.NODE_ENV !== 'production'
const app = next({ dev })
const handle = app.getRequestHandler()
app.prepare().then(() => {
const server = express()
server.get('/blog', (req, res) => {
// #HERE: we redirect request from /blog to /blogs for general page
// so the detail can still be redirected to /blog
return app.render(req, res, '/blogs')
})
server.get('/blog/:id', (req, res) => {
return app.render(req, res, '/blog', { id: req.params.id })
})
server.get('*', (req, res) => {
return handle(req, res)
})
server.listen(port, err => {
if (err) throw err
console.log(`> Ready on http://localhost:${port}`)
})
})
blog.js
import React, { Component } from 'react'
export default class extends Component {
static getInitialProps ({ query: { id } }) {
return { blogId: id }
}
render () {
return (
<div>
<h1>blog {this.props.blogId}</h1>
</div>
)
}
}
blogs.js
import React, { Component } from 'react'
export default class extends Component {
render () {
return (
<div>
<a href="/blog/python">
Learn Python – Interactive <br/> Python
</a>
<a href="/blog/javascript">
Learn Javascript – Interactive <br/> Javascript
</a>
</div>
)
}
}

Next.js Manually Loads Pages via <Link> Without Ajax

I am using Next.js (with Redux, react-i18next, styled components and Express) and Next.js loads my pages without AJAX (with a hard load, no in-place content replacement). Unfortunately, I can't determine the issue of the problem. There's no error in the console (browser and server). Does anyone of you know how to debug this issue or has helpful tips about the problem?
Here's the code of my server:
const express = require('express');
const next = require('next');
const {parse} = require('url');
const i18nextMiddleware = require('i18next-express-middleware');
const Backend = require('i18next-node-fs-backend');
const i18n = require('../hoc/i18n');
const port = parseInt(process.env.APP_PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({dev});
const handle = app.getRequestHandler();
// init i18next with server-side settings
// using i18next-express-middleware
i18n.use(Backend).use(i18nextMiddleware.LanguageDetector).init({
preload: ['en', 'de'],
ns: ['common', 'home', 'content'],
backend: {
loadPath: __dirname + '/../locales/{{lng}}/{{ns}}.json',
addPath: __dirname + '/../locales/{{lng}}/{{ns}}-missing.json',
jsonIndent: 2
}
}, () => {
app.prepare().then(() => {
const server = express();
// Translation routing
server.use(i18nextMiddleware.handle(i18n));
server.use('/locales', express.static(__dirname + '/../locales'));
server.post('/locales/add/:lng/:ns', i18nextMiddleware.missingKeyHandler(i18n));
// Application Routing
server.get('*', (req, res) => {
// Be sure to pass `true` as the second argument to `url.parse`.
// This tells it to parse the query portion of the URL.
const parsedUrl = parse(req.url, true);
const {pathname, query} = parsedUrl;
if (pathname.startsWith('/_next')) {
return handle(req, res, parsedUrl);
} else if (pathname === '/') {
return app.render(req, res, '/', query);
} else {
return app.render(req, res, '/content', query);
}
});
server.listen(port, err => {
if (err) {
throw err;
}
console.log(`> Application server ready on http://localhost:${port}`);
});
})
});
The link itself is created with
<Link href={item.link}>
<a>
{item.title}
</a>
</Link>
Even though the server maps the dynamic URL correctly, the client-side still has to use the following link syntax to make it work (especially important is the "as" attribute):
<Link href={'/content'} as={'/the-real-url'}>
<a>Test Link</a>
</Link>

Express.js - can find my route

I'm using react.js and express.js and getting 404 error on my fetch request.
I'm simply trying to have my routes return testing express.js...
[app.js]
'use strict';
const NODE_ENV = process.env.NODE_ENV;
const PORT = process.env.PORT;
const next = require('next');
const express = require('express');
const api = require('./api');
const client = next({ dev: NODE_ENV === 'development' });
const clientHandler = client.getRequestHandler();
const app = express();
client.prepare().then(() => {
app.use('/api', api);
app.get('*', (req, res) => clientHandler(req, res));
});
const listener = app.listen(PORT, err => {
if (err) throw err;
console.log('listening on port: %d', listener.address().port); //eslint-disable-line
});
[/api/index.js]
'use strict';
const express = require('express');
const app = express();
app.get('/api/test', function (req, res) {
res.send('testing express.js...');
});
module.exports = app;
[Body.js]
import React from 'react';
export default class Body extends React.Component {
constructor(props) {
super(props);
this.fetchContacts = this.fetchContacts.bind(this);
}
componentDidMount() {
this.fetchContacts();
}
async fetchContacts() {
const res = await fetch('/api/test');
const contacts = await res.json();
log(contacts);
this.setState({ contacts });
}
render() {
return <div>hello world!</div>;
}
}
Question: Why am I getting a 404 error?
To make your /api/test route work properly, you need to change this:
app.get('/api/test', function (req, res) {
res.send('testing express.js...');
});
to this:
app.get('/test', function (req, res) {
res.send('testing express.js...');
});
Your router is already looking at /api so when you then put a route on the router for /api/test, you were actually making a route for /api/api/test. To fix it, make the above change.
Also, your index.js file should not be using an app object. It should be using an express.Router() object, though an app object is also a router so it might kind of work, but it's not the way it should be done.
That is not the way to load a react JS file on nodejs, follow this basic (React + NodeJS) guide:
https://blog.yld.io/2015/06/10/getting-started-with-react-and-node-js/#.Wd7zSBiWbyg
Or use "create-react-app" :
https://medium.com/#patriciolpezjuri/using-create-react-app-with-react-router-express-js-8fa658bf892d

Resources