using React router with Next JS route - javascript

i have simple question , i am new in Next.JS
we have a project and my web application manage routes in BackEnd with Next JS
now my problem is here , i want use React-Router-dom in one section
forexample before im working with Laravel and React
in Laravel I set My Route like This
Route::get('/reactPage/*' ...)
and then use Clien route with react
but i dont know how handle this with Next JS
( more details => for example i want user click to some link after that user see a page with some link inside of them , if user click that link , react-router-dom handle route and no any request send to Server )

I would recommend using the Next router. You do need to create a custom server in order to overload the default Next routing, but its a trivial task:
// server.js
const { createServer } = require('http');
const next = require('next');
const routes = require('./routes');
const port = parseInt(process.env.PORT, 10) || 3000;
const dev = process.env.NODE_ENV !== 'production';
const app = next({ dev });
const handler = routes.getRequestHandler(app);
app.prepare().then(() => {
createServer(handler).listen(port, err => {
if (err) {
throw err;
}
console.log(`> Ready on http://localhost:${port}`);
});
});
Then you can define routes, which I do in the routes.js file:
// routes.js
const nextRoutes = require('next-routes');
const routes = (module.exports = nextRoutes());
routes
.add('landing', '/')
.add('profile', '/profile', 'profile');

Related

404 Error when page gets refreshed/revisited

Tried using history mode in vue.js to remove hash sign from the URL. Downside of this is when the page got refreshed / revisited, it occurs 404 Not Found. There's a documentation from the website about the History Mode and fixing it but I'm having trouble understanding it, sorry.
What I want is remove the history mode from the code, at the same time hash symbol gets removed from the url and 404 Error will be fixed.
I will provide the code below from the index.js that the web has. (Note: The website is already built this way and it was passed onto me since the developer that made this had problems.)
Vue.use(VueRouter);
const originalPush = VueRouter.prototype.push;
VueRouter.prototype.push = function push(location) {
return originalPush.call(this, location).catch((err) => err);
};
const router = new VueRouter({
mode:"history",
routes,
});
const isLogin = true;
router.beforeEach((to, from, next) => {
document.title = to.meta.title;
if (to.name == "login" || isLogin) {
next();
} else {
next("/login");
}
});
router.beforeResolve((to, from, next) => {
next();
});
router.afterEach((to, from) => {
});
export default router;
Do I need to do a new set of codes for me to able to do what I want? 404 Error fixed when page got refreshed / revisited, hash symbol gets removed from URL.
The default mode for Vue Router is hash mode. It uses a URL hash to simulate a full URL so that the page won’t be reloaded when the URL changes. Comment or remove mode: "history"
const router = new VueRouter({
//mode:"history",
routes,
});
See the example case here https://www.bezkoder.com/integrate-vue-spring-boot/
I encountered this problem some time ago, you just have to configure the vue router mode and install a package for the server, and configure the server as well. I leave the official guide here.
Vue router config:
const router = new VueRouter({
mode: 'history',//Set the mode to 'history'
routes: [...]
})
Server config (NOT express):
const http = require('http')
const fs = require('fs')
const httpPort = 80
http.createServer((req, res) => {
fs.readFile('index.html', 'utf-8', (err, content) => {
if (err) {
console.log('We cannot open "index.html" file.')
}
res.writeHead(200, {
'Content-Type': 'text/html; charset=utf-8'
})
res.end(content)
})
}).listen(httpPort, () => {
console.log('Server listening on: http://localhost:%s', httpPort)
})
For express node.js sever: For Node.js/Express, consider using connect-history-api-fallback middleware.

Next.js grpc-node usage

I use gRPC but I have a problem initializing the service in Next.js app.
Goal: Create client service only once in app and use it in getServerSideProps (app doesn't use client-side routing).
For example, we have a service generated with grpc-tools (only available on SSR) and then I just want to initialize it somewhere. At first I thought it can be realized in a custom server.js:
const { credentials } = require('#grpc/grpc-js');
const express = require("express");
const next = require("next");
const { MyserviceClient } = require('./gen/myservice_grpc_pb');
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();
// Init & Export
exports.myService = new MyserviceClient(
'http://localhost:3000',
credentials.createInsecure(),
);
(async () => {
await app.prepare();
const server = express();
server.get("*", (req, res) => handle(req, res));
server.listen(process.env.PORT, () => {
console.log(`Listening at http://localhost:${process.env.PORT}`);
});
})();
And then use it on the homepage, for example:
import React from 'react';
const { GetSmthRequest } = require('../gen/myservice_pb');
const { myService } = require('../server.js');
const IndexPage = () => (
<div>
<span>My HomePage</span>
</div>
)
const getServerSideProps = async () => {
const request = new GetSmthRequest();
request.setSomeStuff('random');
myService.getStmh(GetSmthRequest, (err, res) => {
//...
})
return {
props: {
}
}
}
export default IndexPage;
But for some reason it's not possible to initialize the client service in the server.js.
Also I tried doing it with next.config.js:
const { credentials } = require('#grpc/grpc-js');
const { MyserviceClient } = require('./gen/myservice_grpc_pb');
module.exports = {
serverRuntimeConfig: {
myService: new MyserviceClient(
'http://localhost:3000',
credentials.createInsecure(),
),
},
};
This solution works, so I can use the service through serverRuntimeConfig, thereby initializing it only once in the entire application, but when I make a request somewhere using getServerSideProps, I get an error:
Request message serialization failure: Expected argument of type ...
Error explanation: (https://stackoverflow.com/a/50845069/9464680)
That error message indicates that message serialization
(transformation of the message object passed to gRPC into binary data)
failed. This generally happens because the message object doesn't
match the expected message type or is otherwise invalid
Does anyone know why I am getting this error?
It's also interesting to see some examples of using Next.js with grpc-node.
For such a case you can use Node.js global

next.js app with custom server is not rendering correctly

I'm new to next.js so maybe I'm missing something very stupid. I want to use custom routes so I created a server.js file and changed my package.json command to node server.js. This is the entire server.js file:
const express = require("express");
const next = require("next");
const createLocaleMiddleware = require("express-locale");
const dev = process.env.NODE_ENV !== "production";
const app = next({ dev });
const handle = app.getRequestHandler();
app
.prepare()
.then(() => {
const server = express();
server.get("/", createLocaleMiddleware(), (req, res) => {
res.redirect(`/${req.locale.language}/home`);
});
server.get("/:lang/home", (req, res) => {
const actualPage = "/";
const queryParams = { locale: req.params.lang };
app.render(req, res, actualPage, queryParams);
});
server.listen(3000, err => {
if (err) throw err;
console.log("> Ready on http://localhost:3000");
});
})
.catch(ex => {
console.error(ex.stack);
process.exit(1);
});
I believe that according to the docs, this should work. I just want to render the index page with the users locale on the specified route ('/:lang/home'). I'm using react-intl for the i18n.
Now I get the following error in the console (client side):
It's in dutch but it's just saying it can't find any of the specified files. So now the HMR is not working anymore, routing is not working anymore (with Router.push). The only thing it does correctly is loading the index page (I can see it in the browser).
I also tried to enable and disable this flag from the docs:
module.exports = {
useFileSystemPublicRoutes: false
}
Sadly, no effect.
Am I missing something? Is it because I'm redirecting? Or is this not to way to handle routing? If someone could provide some pointers that would be great :)
Thanks in advance!
You are missing server.get('*', handle) as you can see in the custom server express example. This is absolutely required :)

Get middleware mount point from request in Express

I have an Express application with a router, here is the example of the router:
const router = require('express-promise-router')();
const users = require('./users');
const validate = require('./validate');
router.get('/users', users.list);
router.get('/users/:id', users.get);
// other routes here
module.exports = router;
Now I want to add a middleware that validates each query, like that (this is not the working example, it's just to show the idea of what I want to accomplish):
const schemas = {
'/users': 'some validation schema',
'/users/:id': 'another validation'
}
module.exports = (req, res, next) => {
const url = req.originalUrl; // This is where I'm stuck.
if (!schemas[url]) {
// throw new error that validation failed
}
// validating somehow
if (!req.validate(schemas[url])) {
// throw new error that validation failed
}
return next();
}
And for this, I need to get the middlelware mount folder (like '/users/:id' for '/users/557'). I've tried to use req.originalUrl, but it returns the full URL path instead of the mount folder.
How can I achieve this? And if there's no way, how can I write my validation middleware another way to make it work?
Inside req.route you will get the path of API.
Check this screenshot

Koa pass data from server to client

I want to pass through some environment variables from a Koa server to the client. In express I could do something like res.render('index', { data: 'someData' }); and then I could access data. In Koa I can't see how to do this. It mentions using context.state but I can't find any example of how to retrieve this in the client.
You can do something similar in Koa, you just need to use the right middleware. Try out koa-views if you're using one of the supported engines.
Here is a full example (this example assumes you're using Koa v1 and EJS as your templating engine):
app.js
const Koa = require('koa')
const views = require('koa-views')
const router = require('./routes')
const app = new Koa()
app.use(views(__dirname + '/views', { extension: 'ejs' }))
app.use(router.routes())
app.use(router.allowedMethods())
app.listen(3000)
routes.js
const router = require('koa-router')()
router.get('/', function * () {
yield this.render('index', { title: 'Home' })
})
router.get('/about', function * () {
yield this.render('about', { title: 'About' })
})
module.exports = router
Just change the extension argument you pass to the middleware based on which templating engine you are using.

Categories