getInitialProps does not work when the page reload - node.js

I'm using getInitialProps in the _app.js component, but when I reload the page, the request does not execute.
For example:
// getData.js
import * as axios from 'axios';
export default async function getData() {
const response = await axios.get('http://someapi.com/');
return response.data;
}
And then I'm going to use that data...
// _app.js
import getData from './getData';
import App, { Container } from "next/app";
class MyApp extends App {
static async getInitialProps() {
const response = await getData();
if (response) {
return { response };
}
return {};
}
render() {
const { Component, response } = this.props;
<Container>
<Component {...this.props} data={response} />
</Container>
}
}
The first time, it works perfectly, but when I reload the page the getInitialProps() function does not executes :(
How can I resolve this?
Thank you.

Related

useContext auth hook returning null

I have created a useAuth hook in order to allow the user access to the private route once authorised the authorising cookie is stored properly but the useAuth hook seems to be returning null. I also tried printing the value of setUser but it doesn't seem to print after the line setUser(res.data.currentUser) but the one before is printed I cannot figure out why.
The cookies are stored and set properly it just seems to be the auth hook that return setUser as null even though the line console.log("RES>DATA = ", res.data.currentUser); logs the correct details of the cookie but when I try to manually change the url to the private route after the cookie is stored it returns a null for the setUser returned from the auth hook and so access to private route isn't granted. This is done using react for frontend with node js and express for the backend. If any more context is necessary please let me know.
useAuth hook:
import { useState, useContext, useEffect } from "react";
import { UserContext } from "./UserContext";
import axios from "axios";
export default function useAuth() {
const { setUser } = useContext(UserContext);
const [error, setError] = useState(null);
useEffect(() => {
console.log("USE effect");
setUserContext();
});
//set user in context and push them home
const setUserContext = async () => {
console.log("In here");
return await axios
.get("auth/checkAuth")
.then((res) => {
console.log("RES>DATA = ", res.data.currentUser); // PRINTS THE CORRECT COOKIE VALUES
setUser(res.data.currentUser); // THIS SEEMS TO BE NULL?????
console.log("SET USER + ", setUser); // THIS DOES NOT PRINT
})
.catch((err) => {
setError(err);
});
};
return {
setUser,
};
}
Private route:
import React, { useContext } from 'react';
import {Route, Redirect, Navigate} from 'react-router-dom';
import { UserContext } from '../hooks/UserContext';
import useAuth from '../hooks/useAuth';
export default function PrivateRoute({children}) {
const auth = useAuth();
console.log("aUTH in priv = ", auth);
return auth ? children : <Navigate to="/"/>
}
App.js:
import "./App.css";
import { Redirect, Route, Routes, Switch } from "react-router-dom";
import useFetch from "./useFetch";
import { useEffect, useState, useRef } from "react";
import axios from "axios";
import Activities from "./components/Activities";
import HomePage from "./components/Home";
import Map from "./components/Map";
import checkUser from "./hooks/checkUser";
import { UserContext } from "./hooks/UserContext";
import useFindUser from "./hooks/checkUser";
import PrivateRoute from "./components/PrivateRoute";
function App() {
const [auth, setAuth] = useState(false);
const [activities, setActivities] = useState([]);
const notInitialRender = useRef(false);
const { user, setUser, isLoading } = useFindUser(); // works as expected
return (
<div className="App">
<UserContext.Provider value={{ user, setUser, isLoading }}>
<Routes>
<Route path="/" element={<HomePage />}></Route>
<Route path="/Activities" element={<Activities />} />
<Route
path="/Private"
element={
<PrivateRoute>
<Map />
</PrivateRoute>
}
/>
</Routes>
</UserContext.Provider>
</div>
);
}
export default App;
auth/checkAuth express route:
export const checkAuth = (req, res) => {
let currentUser;
console.log("res.cookies = ", req);
if (req.cookies.currentUser) {
// res.send(200);
currentUser = req.cookies.currentUser; // set to user object in cookies
console.log("current user = ", currentUser);
// return 200 status code
} else {
currentUser = null;
}
//res.json(currentUser);
res.status(200).send({ currentUser });
};
Map component which is private route component:
import react from 'react';
function Map() {
<div>
<p style={{color:'red'}}>You have access to the private route</p>
</div>
}
export default Map;
UserContext file:
import { createContext } from "react";
export const UserContext = createContext("null");
I tried logging values and using useEffect to call the function when the useAuth hook is called but couldn't figure it out

NodeJS Axios - Cant show my get request on screen

On this case I am trying to show the "_id".
I made the code based on this video.
But by just looking at his API I can see that his data is little different, how can I adapt it to work with my API
import "./App.css";
import axios from "axios";
import { useEffect, useState } from "react";
const App = () => {
const [leitura, setLeitura] = useState([]);
const getLeituraData = async () => {
try {
const data = await axios.get(
"https://estufaarduino.herokuapp.com/sistema/leituras"
);
console.log(data.data);
setLeitura(data.data);
} catch (e) {
console.log(e);
}
};
useEffect(() => {
getLeituraData();
}, []);
return (
<div className="App">
{leitura.map((item) => {
return <p>{item._id}</p>;
})}
</div>
);
};
export default App;

Converting function React component to class component

I'm trying to add a login page to my existing app. Following along this tutorial https://www.digitalocean.com/community/tutorials/how-to-add-login-authentication-to-react-applications
Got stuck in step 3. My app is a class component, while in the tutorial it's a function component.
How can I convert this to a class component?
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import './App.css';
import Dashboard from '../Dashboard/Dashboard';
import Login from '../Login/Login';
import Preferences from '../Preferences/Preferences';
function setToken(userToken) {
sessionStorage.setItem('token', JSON.stringify(userToken));
}
function getToken() {
const tokenString = sessionStorage.getItem('token');
const userToken = JSON.parse(tokenString);
return userToken?.token
}
function App() {
const token = getToken();
if(!token) {
return <Login setToken={setToken} />
}
return (
<div className="wrapper">
...
</div>
);
}
export default App;
I've tried as below, but it says getToken is not defined inside of a render.
import React from 'react';
import { BrowserRouter, Route, Switch } from 'react-router-dom';
import './App.css';
import Dashboard from '../Dashboard/Dashboard';
import Login from '../Login/Login';
import Preferences from '../Preferences/Preferences';
export default class App extends Component {
constructor(props) {
super(props);
this.state = {
token: undefined
}
this.setToken = this.setToken.bind(this);
this.getToken = this.getToken.bind(this);
}
setToken(userToken) {
sessionStorage.setItem('token', JSON.stringify(userToken));
}
getToken() {
const tokenString = sessionStorage.getItem('token');
const userToken = JSON.parse(tokenString);
return userToken?.token;
}
render() {
const {token} = getToken(); /* In this line getToken is not defined */
if (!token) {
return <Login setToken={(newToken) => this.setState({ token: newToken })} />
}
return (
<div className="pomodoro-clock">
</div>
);
}
I see in the original code, getToken and setToken declared outside of an app. I've tried this, but anyway, getToken is not defined .
I can provide the full code if needed. Any help is appreciated.
If you want to make the functions members of the class, then you need to refer to it using this.getToken(), not just getToken();
render() {
const {token} = this.getToken();
Though since the getToken and setToken functions don't make any reference to this they don't actually need to part of the class. You could keep them outside the class, and refer to them the same way the function component refers to them:
function setToken(userToken) {
sessionStorage.setItem('token', JSON.stringify(userToken));
}
function getToken() {
const tokenString = sessionStorage.getItem('token');
const userToken = JSON.parse(tokenString);
return userToken?.token
}
export default class App extends Component {
constructor(props) {
super(props);
}
render() {
const {token} = getToken();
// ...
}
}

How to receive JSON Object from node and display it on client side in react?

I am sending a json object using res.json. On the client side I am trying to set the json object to a piece of state.
Ive tried to .json() the response but that still does not let me assign it.
This is the server side sending the JSON File
app.get('/api/getPlace', async (req, res) => {
const response = await client.search({
searchType: "Coffee",
location: "San Francisco, CA",
})
const foodPlace = response.jsonBody.businesses[9];
console.log(foodPlace);
res.json(foodPlace)
})
Below is the whole component file to render the json object
import React, { Component } from 'react';
import axios from 'axios';
class RandomPlace extends Component {
constructor(props) {
super(props);
this.state = {
response: {},
};
}
async componentDidMount() {
const res = axios.get('/api/getPlace');
this.setState({ response: res.data })
}
render() {
return (
<div>
{this.state.response}
</div>
);
}
}
export default RandomPlace;
The client call must be awaited:
async componentDidMount() {
const res = await axios.get('/api/getPlace');
this.setState({ response: res.data })
}
import React, { Component } from 'react';
import axios from 'axios';
class RandomPlace extends Component {
constructor(props) {
super(props);
this.state = {
response: {},
};
}
async componentDidMount() {
const res = await axios.get('/api/getPlace');
this.setState({ response: res.data })
}
render() {
return (
<div>
{this.state.response}
</div>
);
}
}
export default RandomPlace;
REST api calls are asynchronous, which means the code proceeds to the next statement without waiting for the api call to compelete. When await is adding before the call, the execution will pause till the call completes or timesout (if specified) before proceeding to the next line. async/await is a better alternative to promises.

TypeError: Cannot read property 'map' of undefined in reactjs

I'm working on an app with expressjs and reactjs. I fetched the data from the backend using expressjs but I get map is not a function.
import React, { Component } from "react";
import "./products.css";
import Listofproducts from "./listofproducts";
import { Link } from "react-router-dom";
class products extends Component {
constructor(props) {
super(props);
this.state = {
productInfo: ""
};
}
async getProducts() {
try {
const data = await fetch("http://localhost:4000/product");
const jsonData = await data.json();
this.setState({
productInfo: jsonData
});
console.log(this.state.productInfo);
} catch (error) {
console.log(error);
}
}
componentDidMount() {
this.getProducts();
}
render() {
return (
<React.Fragment>
<Listofproducts itemlists={this.state.productInfo} />
</React.Fragment>
);
}
}
export default products;
Here is the component productLists where I sent the props to work with it.
import React, { Component } from "react";
import Product from "./products";
class Listofproducts extends Component {
render() {
const { itemslist } = this.props;
console.log(itemslist);
// console.log is working here i get back the data on the console
return itemslist.map(list => {
console.log(list);
});
}
}
export default Listofproducts;
You set productInfo to an empty string in the constructor of products, and strings don't have a map method.
Change the default value to an empty array instead and it will work just as well before and after your network request completes.
class Products extends Component {
constructor(props) {
super(props);
this.state = {
productInfo: []
};
}
// ...
}

Resources