How to retrieve data from URL path with React? - reactjs

On my server side I'am doing this with express :
app.get('/rooms/:id', function(req, res) {
res.sendFile(path.join(__dirname + '/src/index.html'));
});
This sends an index.html file containing a React component. How can I retrieve the ":id" in the URLfrom within the React component?

Simple answer :
assuming you avoid all other libraries and frameworks, you can simply use the location global variable, you will however need to destruct the query params and map them to your argument (usually located inside location.search).
The complex answer:
Most routing libraries(including React Router) will expose an interface to both describe and map GET variables to named variables.

The url params are located inside the req.params object.
app.get('/rooms/:id', function(req, res) {
let roomId = req.params.id;
res.sendFile(path.join(__dirname + '/src/index.html'));
});

Related

How to server-side render a specific route in ReactJS?

I would like to server-side render only a specific route in React. For example, /home should be client-side rendered, but /post should be server-side rendered.
The /post route receives a post ID as a parameter(using react-router) and fetches the content from a database server.
Is their any way I can server-side render only a specific page/route using react-dom server?
Your data should be handled by the middleware and stored there to minimize api calls. The Front end should render based on that data.
One good approach is to use built version of your react within express.js server. So let's say you have your built version of your react inside build directory :
var express = require('express');
var app = express();
app.use("/post",function(req,res) {
console.log(req); // Do your stuff for post route
});
app.use("/",express.static(path.join(__dirname,"/build")));
app.use("/*",express.static(path.join(__dirname,"/build"))); // Handle react-router
const httpServer = require("http").createServer(app);
httpServer.listen(8080, function(){
console.log("Server is running on 8080");
});

Need help about nextjs dynamic url

I am having this problem that whenever i try to visit the page localhost:3000/blog/test directly it returns a 404 error. But whenever i try to visit it using <Link> component it works fine.
This is my code <Link href={{ pathname: '/blog', query: {slug: 'test'} }} as="/blog/test"><a className="nav__link">Blog</a></Link>
and i have a file blog.js in my pages folder.
What's happening is that on the client, with the Link component, you are creating a link to the blog.js page by setting "/blog" as the pathname.
When you go directly to the URL/blog/test, Next.js will try to render the page on the server and to do so will look for the file /pages/blog/test.js. That file doesn't exist, and Next.js doesn't know that you want to load the blog.js page and set query.slug to to the second part of the URL.
To do this, you need to map that route on the server to load the page you want, and pull the params you want out of the URL.
The Next.js docs cover this in Server Side Support for Clean URLs by using express to setup a custom server.
You can view the full code to get it working there, but your custom route will look something like this:
server.get('/blog/:slug', (req, res) => {
const actualPage = '/blog'
const queryParams = { slug: req.params.slug }
app.render(req, res, actualPage, queryParams)
})
You'll have to use now.json to set up your routes. Also it is important to note that it's now that builds the route so visiting it on the client side wont work if you are using localhost. Build your project with now and it should work.
Also the "as" parameter would be as={{ pathname:/user/manage/${variable}}}

Accessing data inside my API with axios post request

I'm trying to send an object with my get request so I can use it to retrieve data from the backend like so:
axios.get('/', {
params: {
mainID: usersID.id,
otherID: usersID.otherID
}
});
Now at my API I want to access that params object, how do I do that?
router.get('/', (req, res) => {
//how to access params?
});
You can access the route parameters in Express by req.params
From the documentation:
Route parameters are named URL segments that are used to capture the values specified at their position in the URL. The captured values are populated in the req.params object, with the name of the route parameter specified in the path as their respective keys.
Route path: /users/:userId/books/:bookId
Request URL: http://localhost:3000/users/34/books/8989
req.params: { "userId": "34", "bookId": "8989" }
Take a look at the Route Parameters section at: https://expressjs.com/en/guide/routing.html
Hope this helps!

How do I create a globally accessible variable in React JS

In my react JS app, I make many API calls,
Rather than having to specify:
const BASE_URL = 'https://apiurlgoeshere.com/'
on every page, I'd rather have BASE_URL accessible throughout the entire application, so I can just do BASE_URL + API_CALL for example
If this is just adding BASE_URL, then this can be achieved by declaring it inside a constants.js file and exporting it from there. But then, that makes us do BASE_URL + "something" each time we make a network request which isn't really ideal either. Also there might be some scenarios where other configuration have to be shared, like say, a common header that has to be added to all the requests.
To solve this, most request libraries have in-build solutions. If we are choosing axios as the most popular one, we can create a instance like:
const instance = axios.create({
baseURL: 'https://some-domain.com/api/',
timeout: 1000,
headers: {'X-Custom-Header': 'foobar'}
});
export default instance;
and import this everywhere the axios is going to be used like:
import axios from "./axios-instance";
assuming axios-instance.js is the file where the instance is created. Now you can skip adding the BASE_URL to every request as it is already provided in the instance.
If webpack is being used for code bundle, DefinePlugin can be used.
new webpack.DefinePlugin({
'BASE_URL': JSON.stringify('https://apiurlgoeshere.com/')
});
For gulp build, gulp-replace can be used.
.pipe(replace('BASE_URL', 'https://apiurlgoeshere.com/'))
I know it's been a while since I created this post - just wanted to go through what I've learnt really.
It's a great way to set a global config for Axios. I typically create a folder and create an api.js file within it which I use to make all of my API calls, this is great as it means you only have to specify headers / base URL / credentials etc once.
Here is a code example for a solution:
function apiCall (method, path, data) {
let url = "https://urltoyourapis.com/";
return new Promise((resolve, reject) => {
return Axios[method](url, {headers}, data).then(res => {
return resolve(res);
}).catch(err => {
return reject(err);
})
})
}
Now, whenever you want to make an API call you'd import this function into the file where you would like to make the API call and do the following:
apiCall("get", "account-info")
This will then make an API call to the endpoint "account-info" to get the information, you can either await and set the result to a variable or use .then .catch to handle the response.

Refreshing a react router page that has a dynamic url/params

I have several components displayed with react router that have dynamic url paths. An example path I have is
<Route path="/newproject/:id" onEnter={checkSesh} component= {ProjectDetails} />
When entering this component, I have a componentWillMount function that extract the id part of the url so that I can get the info for the correct project and render it on the ProjectDetails component.
componentWillMount() {
var id = this.props.router.params.id
this.props.teamDetails(id);
}
this.props.teamDetails(id) this calls a redux action creator that will make an axios request to an express route that will get the project info from the database.
export function teamDetails(id) {
return function(dispatch) {
axios.get('/getteaminfo/' + id)
.then(res => {
dispatch({ type: "SET_TEAM_DETAILS", payload: {
teamInfo: res.data.teamInfo,
admin: res.data.admin,
adminID: res.data.teamInfo.teamAdmin,
teamMembers: res.data.teamInfo.teamMembers
}
})
});
}
}
everything works fine upon visiting the page after already being logged in etc. But when I refresh the page /newproject/:id, i get an error Uncaught SyntaxError: Unexpected token <. An example url in my browser looks like http://localhost:3000/newproject/58df1ae6aabc4916206fdaae. When I refresh this page, I get that error. The error is complaining about my <!DOCTYPE html> tag at the very top of my index.html for some reason. This index.html is where all of React is being rendered.
When page is refreshed store state is not preserved. Make sure the state is not important to load the page, or at least initialized properly every time.
For e.g. login information if saved in store and not on browser with localStorage or cookies etc.. then on refresh, the error will come when trying to access /getteaminfo/ route through axios. The response will have error html and it can't be parsed by js.
Please check your web console on for more information. You can use chrome extension like https://github.com/zalmoxisus/redux-devtools-extension which will show your store and etc..
Make sure to check what /getteaminfo/ gives with id is not passed.
Also, make sure on your server side, did you route requests to react-router path through something like this?
e.g. express js,
app.get('*', function response(req, res) {
res.sendFile(path.join(__dirname, 'public', 'index.html'));
});
be sure to sendFile with the real location of index.html
I found the answer here: react-router dynamic segments crash when accessed I added <base href="/" /> into the <head>of my index.html. You can also read more info here: Unexpected token < error in react router component

Resources