Reputation: 603
I have a React.js and Next.js app where I need to pass the User object to all the pages. I then plan to pass this User component to Head component so that I can show different navigation based on user role. This is what I have so far:
This is _App.js where I check if user token exists. If it exists, I verify it by calling an API and then I assign the result to pageProps. This pageProps is then passed to other components.
import '../styles/global.css'
import CustomTheme from '../styles/custom-theme';
import { ThemeProvider } from '@material-ui/styles';
import { getToken, setUserSession } from '../utils/common';
import React, { useState, useEffect } from 'react';
function MyApp({ Component, pageProps }) {
useEffect(()=>{
const token = getToken();
console.log(token)
if (!token){
console.log('no token')
return;
}
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'x-access-token': token },
//body: token
};
fetch("http://localhost:3600/auth/verifyToken", requestOptions)
.then(res => res.json())
.then(
(result) => {
pageProps.user = JSON.stringify(result);
console.log('verifyToken response 2 : ' + JSON.stringify(result))
})
},[])
console.log(pageProps)
return (
<ThemeProvider theme={CustomTheme}>
{/* <Component {...pageProps} /> */}
<Component {...pageProps} />
</ThemeProvider>
)
}
export default MyApp
Then, in my waiting-room.js page, I try to get hold of this prop and print it:
export default function WaitingRoom(pageProps) {
const classes = useStyles();
const [selectedValue, setSelectedValue] = useState('yes');
const [error, setError] = useState(null);
const [isLoaded, setIsLoaded] = useState(false);
const [userId, setUserId] = useState(null);
const [childName, setChildName] = useState(null);
const [demoData, setDemoData] = useState(null);
const [counterTime, setCounterTime] = useState(null);
const [disableJoin, setDisableJoin] = useState(true);
const [classOver, setClassOver] = useState(false);
const [demoBooked, setDemoBooked] = useState(false);
// Note: the empty deps array [] means
// this useEffect will run once
// similar to componentDidMount()
useEffect(() => {
console.log("pageProps : " + JSON.stringify(pageProps.user))
})
}
First time page load, everything is fine. All console.log statements print values as expected. But when I click on browser refresh button, I see pageProps as undefined. And then when I again make some changes on the page and save it, it starts working till I again hit browser refresh. Is it something to do with server side rendering?
Edit post @Siddhart's answer:
Upvotes: 0
Views: 152
Reputation: 1270
You're seeing the weird behavior because you're mutating the original pageProps
object.
Reason why you're not seeing the pageProps
changes
WaitingRoom
isn't aware of any change because reference to the pageProps
remain same.
Reason why you see the pageProps
changes
Probably MyApp
component re-renders due to some prop change which in turn causes the re-render of child component i.e. WaitingFroom
What you need to do is, update state when pageProps
changes so that component re-renders with updated props.
import '../styles/global.css'
import CustomTheme from '../styles/custom-theme';
import { ThemeProvider } from '@material-ui/styles';
import { getToken, setUserSession } from '../utils/common';
import React, { useState, useEffect } from 'react';
function MyApp({ Component, pageProps }) {
const [updatedProps, setUpdatedProps] = useState(pageProps);
// If pageProps change over time
useEffect(() => {
setUpdatedProps(prevUpdatedProps => ({
...prevUpdatedProps,
...pageProps
}));
}, [pageProps])
useEffect(()=>{
const token = getToken();
console.log(token)
if (!token){
console.log('no token')
return;
}
const requestOptions = {
method: 'POST',
headers: { 'Content-Type': 'application/json', 'x-access-token': token },
//body: token
};
fetch("http://localhost:3600/auth/verifyToken", requestOptions)
.then(res => res.json())
.then(
(result) => {
pageProps.user = JSON.stringify(result);
setUpdatedProps({...updatedProps, user: JSON.stringify(result)});
console.log('verifyToken response 2 : ' + JSON.stringify(result))
})
},[])
return (
<ThemeProvider theme={CustomTheme}>
<Component {...updatedProps} />
</ThemeProvider>
)
}
export default MyApp
Upvotes: 2