Pass parameters to another page in React JS - javascript

I'm having a problem where I want the information that is being passed on a page to be sent to another page, this other page I say is like a single page.
I've already tried to pass the parameters of this page to another with props, params, but without any success.
I believe it is something very simple, but it left me without a solution
Homepage.jsx
import React, {useEffect, useState} from 'react';
import * as Styled from './styles';
import OwlCarousel from 'react-owl-carousel';
import 'owl.carousel/dist/assets/owl.carousel.css';
import 'owl.carousel/dist/assets/owl.theme.default.css';
import { FaStar,FaInfoCircle } from "react-icons/fa";
import { NavLink } from 'react-router-dom';
import SinglePage from '../SinglePage';
export default function Home() {
const [data, setData] = useState([]);
useEffect(() => {
fetch('https://api.rawg.io/api/games?key=328c7603ac77465895cf471fdbba8270')
.then((res) => res.json())
.then((data) => {
setData(data.results);
})
.catch((err) => {
console.log(err);
});
}, []);
return (
<>
<Styled.Container>
<div className="boxSite">
<div className="boxBrowse">
<div className="boxAll">
<OwlCarousel className='owl-theme' loop margin={0} items={6} center={true} dots=
{false}>
{data.map((games)=> (
<>
<div className="produto" key={games.id} layoutId={games.id}>
<div className="imagemGame" style={{backgroundImage:
`url(${games.background_image})`}}>
<div className="information">
<NavLink to={{
pathname:`/single-game/${games.slug}`,
}}
>
<span>
<FaInfoCircle/>
</span>
</NavLink>
<SinglePage name={games.name} />
</div>
<div className="classificacao">
<span> Avaliação <b> {games.rating} </b></span>
<span> <FaStar /></span>
</div>
</div>
</div>
</>
))}
</OwlCarousel>
</div>
</div>
</div>
</Styled.Container>
</>
)
}
SinglePage.jsx
import React from 'react';
import * as Styled from './styles';
export default function SinglePage(props) {
return (
<>
<h1>NAME OF THE GAME : {props.name}</h1>
</>
)
}
Yes, I stopped here, please can someone help me?
Information is appearing on the Homepage, but not on the single page

In this case, if you're using version 5 or earlier of router-dom you can pass the data via state, using history:
Change this:
import { NavLink } from 'react-router-dom';
return (
<NavLink to={{
pathname:`/single-game/${games.slug}`,
}}>
<span>
<FaInfoCircle/>
</span>
</NavLink>
)
To this:
import { useHistory } from 'react-router-dom';
const history = useHistory();
return (
<button
onClick(() => history.push(`/single-game/${games.slug}`,{
foo: 'bar',
nameGame,
}))
>
<span>
<FaInfoCircle/>
</span>
</button>
)
And on your page you can get the data via props, like:
import React from 'react';
export default function SinglePage(props) {
const { nameGame } = props.location.state;
return (
<>
<h1>NAME OF THE GAME : {nameGame}</h1>
</>
)
}

It depends on your needs.
If you need to access a lot of data over several pages, you should use a state management library like Redux.
If it's only simple data, you can pass it as query parameters to your page.
If it's a bit more complexe, you can use the session / local storage.
But it's a bit hard to know what to recommend you exactly without more info about what you want to achieve exactly.

Import component into Homepage
import SinglePage from './your-single-page-file';
Use the tag and pass a parameter on the JSX
<SinglePage name={data.variableNeeded} />
On the SinglePage function add the props parameter and use it like this:
import React from 'react';
import * as Styled from './styles';
export default function SinglePage(props) {
return (
<>
<h1>NAME OF THE GAME : {props.name}</h1>
</>
)
}

Since you only included the component that has a single data state that is mapped and renders some links I'll assume it is the games object you want to send to the linked route. Pass the data in route state via the NavLink component.
See NavLink and Link
interface LinkProps
extends Omit<
React.AnchorHTMLAttributes<HTMLAnchorElement>,
"href"
> {
replace?: boolean;
state?: any;
to: To;
reloadDocument?: boolean;
}
Route state is sent along on the state prop of a link component.
Example:
{data.map((games) => (
<div className="produto" key={games.id} layoutId={games.id}>
<div
....
>
<div className="information">
<NavLink
to={`/single-game/${games.slug}`}
state={{ games }} // <-- pass route state
>
<span>
<FaInfoCircle/>
</span>
</NavLink>
<SinglePage name={games.name} />
</div>
....
</div>
</div>
))}
In the receiving component use the useLocation hook to access the passed route state.
Example:
import { useLocation } from 'react-router-dom';
export default function SinglePage() {
const { state } = useLocation();
const { games } = state || {};
...
return (
<>
<h1>NAME OF THE GAME : {games.name}</h1>
</>
);
}

Related

App is not rendering even when the state in the redux is changed

I am having two buttons in a component thats under App component. Even though it is dispatching actions and store is updated, App is not re-rendered. Ideally on button press, I add some dummy name that will be put inside array and then a different component is rendered based on number items inside this array.
Can someone tell what is going wrong, I am a beginner to react and redux
Sandbox: https://codesandbox.io/s/panel-item-with-redux-hxmihq?file=/src/PanelAdder.js
App.jsx
import React from "react";
import "./styles.css";
import { Panel } from "./Panel";
import PanelAdder from "./PanelAdder";
import { useSelector } from "react-redux";
export default function App() {
const panels = useSelector((state) => state.panelItems);
return (
<>
<PanelAdder />
<div className="cards-container">
{panels || [].map((name) => <Panel {...{ name }} />)}
</div>
</>
);
}
PanelAdder.jsx
import React from "react";
import { useDispatch } from "react-redux";
import { addPanel } from "./actions/counterActions";
export default function PanelAdder() {
const dispatch = useDispatch();
const handleClick = (name) => {
dispatch(addPanel(name));
};
return (
<>
<button onClick={() => handleClick("Panel 1")}> Add Panel 1</button>
<button onClick={() => handleClick("Panel 2")}> Add Panel 2</button>
</>
);
}
Panel.jsx
import React from "react";
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome";
import {
faSquareMinus,
faWindowMaximize,
faRectangleXmark
} from "#fortawesome/free-solid-svg-icons";
export const Panel = ({ name }) => {
return (
<>
<div className="card">
<div className="card-actions">
<FontAwesomeIcon icon={faSquareMinus} />
<FontAwesomeIcon icon={faWindowMaximize} />
<FontAwesomeIcon icon={faRectangleXmark} />
</div>
<div className="card-body">{name}</div>
</div>
</>
);
};
You have 2 issues:
First in your combineReducers function you are adding the reducer called panels. Redux will add this to the state object. So when you are referencing it you need to refrence the panels object that is nested inside your state object. You need to get the following in your useSelector useSelector((state) => state.panel.panelItems)
Second you are doing the following in your app component {panels || [].map((name) => <Panel {...{ name }} />)}. So what you are doing here is displaying the panels array or mapping through an empty array but you never actually map through the panels array. But what you need to do is map through the panels array. So you can just map the panels array {panels.map((name) => <Panel {...{ name }} />)}
So your app component should look like the following:
import React from "react";
import "./styles.css";
import { Panel } from "./Panel";
import PanelAdder from "./PanelAdder";
import { useSelector } from "react-redux";
export default function App() {
const panels = useSelector((state) => state.panel.panelItems);
return (
<>
<PanelAdder />
<div className="cards-container">
{panels.map((name) => <Panel {...{ name }} />)}
</div>
</>
);
}

export 'withRouter' (imported as 'withRouter') was not found in 'react-router-dom'. using react-router-dom: 6.0.2 [duplicate]

Failed to compile. Attempted import error: 'withRouter' is not exported from 'react-router-dom'.
My code like, also I have installed react-router-dom an react-route and I have respin the app 10 time now
import React from 'react';
import {withRouter} from 'react-router-dom';
import './menu-item.scss';
const MenuItem = ({ title, imageUrl, size, history }) => (
<div className={`${size} menu-item`}>
<div
className='background-image'
style={{
backgroundImage: `url(${imageUrl})`,
}}
/>
<div className='content'>
<h1 className='title'>{title.toUpperCase()}</h1>
<span className='subtitle'>SHOP NOW</span>
</div>
</div>
);
export default withRouter(MenuItem);
If you accidentally installed react-router-dom v6 then the withRouter HOC no longer exists. Either revert back to v5 (run npm install -s react-router-dom#5), or roll your own custom withRouter HOC to inject the props you need or convert the components to function components and use the React hooks.
Create custom withRouter Higher Order Component
From the FAQ: What happened to withRouter I need it
import {
useLocation,
useNavigate,
useParams,
} from "react-router-dom";
function withRouter(Component) {
function ComponentWithRouterProp(props) {
let location = useLocation();
let navigate = useNavigate();
let params = useParams();
return (
<Component
{...props}
router={{ location, navigate, params }}
/>
);
}
return ComponentWithRouterProp;
}
Convert to function component
There is now also no longer a history object to use, it was replaced by a navigate function accessed via the useNavigate hook. It's not clear where history was being used previously, but if you need to imperatively navigate the following is how you access the navigation. If staying with v6 then the following is how to access the navigate function.
import React from 'react';
import { useNavigate } from 'react-router-dom';
import './menu-item.scss';
const MenuItem = ({ title, imageUrl, size }) => {
const navigate = useNavigate();
// navigate("/targetPath")
return (
<div className={`${size} menu-item`}>
<div
className='background-image'
style={{
backgroundImage: `url(${imageUrl})`,
}}
/>
<div className='content'>
<h1 className='title'>{title.toUpperCase()}</h1>
<span className='subtitle'>SHOP NOW</span>
</div>
</div>
)
};
export default MenuItem;
You can use useLocation hook and destructure 'pathname' property from it to make the navigated link in the onClick() function dynamic.
Here's a sample of the code that worked for me:
import React from "react";
import { useLocation, useNavigate } from "react-router-dom";
import "./menu-item.styles.scss";
const MenuItem = ({ title, imageUrl, size, linkUrl, match }) => {
let navigate = useNavigate();
// destructured "pathname" property from useLocation()
let { pathname } = useLocation();
// consoloe.log(pathname)
return (
<div className={`${size} menu-item`} onClick={() => navigate(`${pathname}${linkUrl}`)}>
<div
className="background-image"
style={{
backgroundImage: `url(${imageUrl})`,
}}
/>
<div className="content">
<h1 className="title">{title.toUpperCase()}</h1>
<span className="subtitle">SHOP NOW</span>
</div>
</div>
);
};
export default MenuItem;
thanks to Drew Reese -great shout-, and similar to Switch ( will throw the same error ) here is the downgrade command, just make sure you are in the right directory
npm install react-router-dom#5.0.0
try this it worked for me
import React from "react";
import { useNavigate } from "react-router-dom";
import "./menu-item.styles.scss";
const MenuItem = ({ title, imageUrl, size, history, linkUrl, match }) => {
const navigate = useNavigate();
return (
<div className={`${size} menu-item`} onClick={() => navigate(`hats`)}>
<div
className="background-image"
style={{
backgroundImage: `url(${imageUrl})`,
}}
></div>
<div className="content">
<h1 className="title">{title.toUpperCase()}</h1>
<span className="subtitle">SHOP NOW</span>
</div>
</div>
);
};
export default MenuItem;
in menu-item.component.jsx you can use the useNavigate just like this one
import React from "react";
import { useNavigate } from "react-router-dom";
import "./menu-item.styles.scss";
const MenuItem = ({ title, imageUrl, size, history, linkUrl, match }) => {
let navigate = useNavigate();
return (
<div className={`${size} menu-item`} onClick={() => navigate(`${linkUrl}`)}>
<div
className="background-image"
style={{
backgroundImage: `url(${imageUrl})`,
}}
></div>
<div className="content">
<h1 className="title">{title.toUpperCase()}</h1>
<span className="subtitle">SHOP NOW</span>
</div>
</div>
);
};
export default MenuItem;
Also, in App.js you should import Routes and Route from react-router-dom and make your code like this:
import React from "react";
import { Routes, Route } from "react-router-dom";
import "./App.css";
import HomePage from "./pages/homepage/homepage.component";
const HatsPage = () => (
<div>
<h1>Hats page</h1>
</div>
);
function App() {
return (
<div>
<Routes>
<Route exact path="/" element={<HomePage />} />
<Route path="/hats" element={<HatsPage />} />
</Routes>
</div>
);
}
export default App;
As for me, this works.

How to use react-router-dom v6 navigate in class component

I installed react-router-dom v6 and I want to use a class based component, in previous version of react-router-dom v5 this.props.history() worked for redirect page after doing something but this code not working for v6 .
In react-router-dom v6 there is a hook useNavigate for functional component but I need to use it in class base component , Please help me how to use navigate in class component ?
In the react-router-dom v6, the support for history has been deprecated but instead of it, navigate has been introduced. If you want to redirect user to a specific page on success of a specific event, then follow the steps given below:
Create a file named as withRouter.js, and paste the code given below in this file:
import { useNavigate } from 'react-router-dom';
export const withRouter = (Component) => {
const Wrapper = (props) => {
const navigate = useNavigate();
return (
<Component
navigate={navigate}
{...props}
/>
);
};
return Wrapper;
};
Now, in whichever class based component you want to redirect the user to a specific path/component, import the above withRouter.js file there and use this.props.navigate('/your_path_here') function for the redirection.
For your help, a sample code showing the same has been given below:
import React from 'react';
import {withRouter} from '.your_Path_To_Withrouter_Here/withRouter';
class Your_Component_Name_Here extends React.Component{
constructor(){
super()
this.yourFunctionHere=this.yourFunctionHere.bind(this);
}
yourFunctionHere()
{
this.props.navigate('/your_path_here')
}
render()
{
return(
<div>
Your Component Code Here
</div>
)
}
}
export default withRouter(Your_Component_Name_Here);
Above Code works Perfect. And this is just a small extension.
If you want onclick function here is the code:
<div className = "row">
<button className= "btn btn-primary"
onClick={this.yourFunctionHere}>RedirectTo</button>
</div>
in class base component for redirect user follow this step :
first import some component like this
import { Navigate } from "react-router-dom"
now make a state for Return a boolean value like this:
state = {
redirect:false
}
now insert Naviagate component to bottom of your component tree
but use && for conditional rendring like this :
{
this.state.redirect && <Navigate to='/some_route' replace={true}/>
}
now when you want redirect user to some page just make true redirect state
on a line of code you want
now you can see you navigate to some page :)
Try this:
import {
useLocation,
useNavigate,
useParams
} from "react-router-dom";
export const withRouter = (Component) => {
function ComponentWithRouterProp(props) {
let location = useLocation();
let navigate = useNavigate();
let params = useParams();
return (
<Component
{...props}
router={{ location, navigate, params }}
/>
);
}
return ComponentWithRouterProp;
}
and just used this function, in my case:
import { withRouter } from '../utils/with-router';
import './menu-item.styles.scss';
const MenuItem = ({title, imageUrl, size, linkUrl,router}) =>(
<div
className={`${size} menu-item`} onClick={() => router.navigate(`${router.location.pathname}${linkUrl}`)}
>
<div className='background-image'
style={{
backgroundImage: `url(${imageUrl})`
}} />
<div className="content">
<h1 className="title">{title.toUpperCase()}</h1>
<span className="subtitle">SHOP NOW</span>
</div>
</div>
)
export default withRouter(MenuItem);
I found this solution here https://www.reactfix.com/2022/02/fixed-how-can-i-use-withrouter-in-react.html
Other solution is useNavigate, for example:
<button onClick={() => {navigate("/dashboard");}} >
Dashboard
</button>
In a react class component use <Navigate>. From the react router docs:
A <Navigate> element changes the current location when it is rendered. It's a component wrapper around useNavigate, and accepts all the same arguments as props.
Try creating a reusable functional Component like a simple button and you can use it in your class component.
import React from "react";
import { useNavigate } from "react-router-dom";
const NavigateButton = ( { buttonTitle, route,isReplaced}) => {
const navigate = useNavigate();
return (
<button
className = "btn btn-primary"
onClick = { () => {
navigate( route , {replace:isReplaced} )
}}
>
{buttonTitle}
</button>;
);
});
export default NavigateButton;
After this, you can use NavigateButton in any of your class Components. And it will work.
<NavigateButton title = {"Route To"} route = {"/your_route/"} isReplaced = {false}/>
Found this explanation from the GitHub react-router issue thread, this explained how to use react-router 6 with class components
https://github.com/remix-run/react-router/issues/8146
I got this code from the above issue explanation
import React,{ Component} from "react";
import { useNavigate } from "react-router-dom";
export const withNavigation = (Component : Component) => {
return props => <Component {...props} navigate={useNavigate()} />;
}
//classComponent
class LoginPage extends React.Component{
submitHandler =(e) =>{
//successful login
this.props.navigate('/dashboard');
}
}
export default withNavigation(LoginPage);
If you need to use params for data fetching, writing a logic in your ClassComponent and render component depending on them, then create wrapper for your ClassComponentContainer
import { useLocation, useParams } from 'react-router-dom';
import ClassComponentContainer from './ClassComponentContainer';
export default function ClassComponentWrap(props) {
const location = useLocation();
const params = useParams();
return <ClassComponentContainer location={location} params={params} />
}
after it just use params in ClassComponent which is in props
import React from 'react';
import { connect } from 'react-redux';
import axios from 'axios';
import PresentationComponent from './PresentationComponent';
class ClassComponent extends React.Component {
componentDidMount() {
let postID = this.props.params.postID;
axios.get(`https://jsonplaceholder.typicode.com/posts/${postID}`)
.then((response) => {console.log(response)})
}
render() {
return <PresentationComponent {...this.props} />
}
}
const mapStateToProps = (state) => {...}
const mapDispatchToProps = (dispatch) => {...}
const ClassComponentContainer = connect(mapStateToProps, mapDispatchToProps)(ClassComponent);
export default ClassComponentContainer;
and use ClassComponentWrap component in Route element attribute
import { BrowserRouter, Route, Routes } from "react-router-dom";
import ClassComponentWrap from './components/ClassComponentWrap';
export default function App(props) {
return (
<BrowserRouter>
<Routes>
<Route path="/posts/:postID?" element={<ClassComponentWrap />} />
</Routes>
</BrowserRouter>
);
}
Here is my solution:
import React, { Component } from "react";
import { useNavigate } from "react-router-dom";
class OrdersView extends Component {
Test(props){
const navigate = useNavigate();
return(<div onClick={()=>{navigate('/')}}>test{props.test}</div>);
}
render() {
return (<div className="">
<this.Test test={'click me'}></this.Test>
</div>);
}
}

How to understand a React file

I am using React in Laravel and I found a problem that I can't refresh or reload a page in React. So to solve this problem I found many suggestions like use historyApiFallback, 404 page and many other ways But I found none of them useful to me now.
I know I can't do this because React has no system for it because of server- and client-side routing. Then i found a demo project where they used Redux and I can refresh their page. I got the demo project where i can use any component and refresh them how many times I want. So there is a file name with Base.js and I am not understanding this file why he used it what is doing. Let me share the file and where it was used.
Base.js
import React from 'react';
import { connect } from 'react-redux';
import Header from './components/Header';
const Base = ({ children }) => (
<div>
<Header />
<main>{children}</main>
</div>
);
const mapStateToProps = (state) => ({
isAuthenticated: state.Auth.isAuthenticated,
});
export default connect(mapStateToProps)(Base);
Header.Js
import React, { Component } from 'react';
import { connect } from 'react-redux';
import { Link } from 'react-router-dom';
import {
Nav,
NavItem,
NavLink,
UncontrolledDropdown,
DropdownToggle,
DropdownMenu,
DropdownItem,
} from 'reactstrap';
import * as actions from '../store/actions';
class Header extends Component {
handleLogout = (e) => {
e.preventDefault();
this.props.dispatch(actions.authLogout());
};
render() {
return (
<header className="d-flex align-items-center justify-content-between">
<h1 className="logo my-0 font-weight-normal h4">
<Link to="/">Laravel React</Link>
</h1>
{this.props.isAuthenticated && (
<div className="navigation d-flex justify-content-end">
<Nav>
<NavItem>
<NavLink tag={Link} to="/archive">
Archive
</NavLink>
<NavLink tag={Link} to="/Myfile">
Myfile
</NavLink>
</NavItem>
<UncontrolledDropdown nav inNavbar>
<DropdownToggle nav caret>
Account
</DropdownToggle>
<DropdownMenu right>
<DropdownItem>Settings</DropdownItem>
<DropdownItem divider />
<DropdownItem onClick={this.handleLogout}>
Log Out
</DropdownItem>
</DropdownMenu>
</UncontrolledDropdown>
</Nav>
</div>
)}
</header>
);
}
}
const mapStateToProps = (state) => ({
isAuthenticated: state.Auth.isAuthenticated,
});
export default connect(mapStateToProps)(Header);
Public.js
import PropTypes from 'prop-types';
import { Route } from 'react-router';
import Base from '../Base';
const PublicRoute = ({ component: Component, ...rest }) => (
<Route
{...rest}
render={(props) => (
<Base>
<Component {...props} />
</Base>
)}
/>
);
PublicRoute.propTypes = {};
export default PublicRoute;
split.js
import React from 'react';
import PropTypes from 'prop-types';
import { Route } from 'react-router';
import { connect } from 'react-redux';
import Base from '../Base';
const SplitRoute = ({
component: Component,
fallback: Fallback,
isAuthenticated,
...rest
}) => (
<Route
{...rest}
render={(props) => (isAuthenticated ? (
<Base>
<Component {...props} />
</Base>
) : (
<Base>
< Fallback {...props} />
</Base>
))}
/>
);
SplitRoute.propTypes = {
isAuthenticated: PropTypes.bool.isRequired,
};
const mapStateToProps = (state) => ({
isAuthenticated: state.Auth.isAuthenticated,
});
export default connect(mapStateToProps)(SplitRoute);
Now it has authenticated system so I understand it but why it is using base function and what it is doing? I am not understanding.
What it looks like is that the Base.js is a container for the Header and any rendered children (passed props). This is a good practise in react to separate logic and make it more readable. So when he imports Base into the Public.js file, it will render the Header and the component he is passing to it from the public function props.
Think of it like the skeleton of the layout, by importing Base it will always render the header and any logic inside of the header file, and whatever he is passing down to it. As you can see he is passing different components to it depending on whether isAuthenticated is true or false. If it is false, they are rendering Base and passing a fallback component - this will render inside of the main tag within the Base function.

why my context doesn't update when the context value updates?

so I am using React's context API in my Gatsby app(which is written in React basically) to deal with user authentication. I have two components that use that context: dashboard and navBar. When I try to log in and log out, my navBar will behave differently according to my userContext, but my dashboard won't respond. Is it something related to the structure, like navBar is the direct "children" to layout, but dashboard is not? I assume not though, after all, that's why I use contextAPI then just pass a normal prop.
Here are the codes:
//layout.js
import React, { useContext, useState, createContext } from "react"
import Navbar from "../components/navBar"
import {monitorAuth} from "../firebase/firebaseService"
export const UserStateContext = createContext(null)
export const SetUserContext = createContext()
const Layout = ({ children }) => {
const [user, setUser] = useState()
console.log(user)
monitorAuth(setUser)// everytime a layout component renders, it will grab a user if it is logged inthen setUser, then I will use it in the context
return (
<>
<UserStateContext.Provider value={user}>
<SetUserContext.Provider value={setUser}>
<div>
<SEO />
<Navbar />
<main>{children}</main>
</div>
</SetUserContext.Provider >
</UserStateContext.Provider>
</>
)
}
export default Layout
import React, { useState, useContext } from "react"
import AppBar from "#material-ui/core/AppBar"
import { signOut } from "../firebase/firebaseService"
import {UserStateContext} from "./layout"
export default function NavBar() {
const user = useContext(UserStateContext)
console.log(user) // when I log in/ log out, it will console.log the right user status, user/null
const renderMenu = () => {
return (
<>
{user? (
<>
<Button onClick={signOut}>Sign Out</Button>
<Button>My profile</Button>
</>)
:<Button>Sign In</Button> }
</>
)
}
return (
<AppBar position="static" className={classes.root}>
...
{renderMenu()}
...
</AppBar>
)
}
//dashboard.js
import React, { useContext } from 'react'
import Layout from '../components/layout'
import LoggedIn from '../components/dashboard/loggedIn'
import NotLoggedIn from '../components/dashboard/notLoggedIn'
import {UserStateContext} from "../components/layout"
const Dashboard = props => {
console.log("within dashboard")
const user = useContext(UserStateContext)
console.log(user)
const renderDashboard = () =>{
return (
<>
{user? <LoggedIn /> : <NotLoggedIn />}
</>
)
}
return(
<Layout>
{renderDashboard()}
</Layout>
)
}
export default Dashboard
One more clue, I console.log user in all three components and when I refresh the page:
within dashboard
dashboard.js:17 null
layout.js:15 undefined
navBar.jsx:54 undefined
layout.js:15 [user...]
navBar.jsx:54 [user...]
layout.js:15 [user...]
That means, at first, user is not set yet, so all three components log the user as undefined, but later, layout detect the user and then updates it, so navbarknows too, but dashboard doesn't. Is it something about re-render? Thanks!
The reason it's not working is because your <Dashboard> component is not a child of the context provider. If you use React devtools, you'll see the component tree looks like
<Dashboard>
<Layout>
<UserStateContext.Provider>
<SetUserContext.Provider>
...
</SetUserContext.Provider>
</UserStateContext.Provider>
</Layout>
</Dashboard>
When the context value changes, it looks for components in its subtree that useContext. However, Dashboard is not a child, it's the parent!
If you want to follow this pattern, a solution may be to create a parent component of Dashboard and put the context there.

Categories