Reputation: 2205
I'm a beginner and need advice. I learn Reactjs and created this HOC so I could navigate in the Router V6. My concern is that from my desktop Navbar
and from the mobile side menu I have links to the same Dashboard
.
So I create a HOC since it's the same code running in both locations and the HOC now have this code.
This is the HOC:
import React from 'react';
import AuthUserContext from './context';
import * as ROLES from '../constants/roles';
const WithDashboardNavigate = Component => {
class WithDashboardBase extends React.Component {
constructor() {
super();
this.onDashboard = this.onDashboard.bind(this);
}
onDashboard = navigate => {
const { authUser } = this.props;
if (authUser) {
if (authUser.roles.includes(ROLES.ANON)) {
navigate('/app/login');
} else if (authUser.roles.includes(ROLES.USER) || authUser.roles.includes(ROLES.ADMIN)) {
const view = localStorage.getItem('currentDashBoardView');
// Here if user has used nav menu earlier then that last view is loaded
if (view) navigate(view);
// or default to dash
else navigate('/app/dashboard');
}
}
};
render() {
return <Component dashboardNavigater={this.onDashboard} {...this.props} />;
}
}
const WithDashboard = () => (
<AuthUserContext.Consumer>
{authUser => (
<div>
<WithDashboardBase authUser={authUser} />
</div>
)}
</AuthUserContext.Consumer>
);
return WithDashboard;
};
export default WithDashboardNavigate;
And I use it like this from Navbar
:
function SignedInButton(props) {
const navigate = useNavigate();
function openDashboard() {
props.dashboardNavigater(navigate);
}
return (
<div>
<Button className="button is-large" onClick={openDashboard}>
<span className="icon is-medium">
<i className="fas fa-user" />
</span>
</Button>
</div>
);
}
export default WithDashboardNavigate(SignedInButton);
And I use it like this from SideMenu
:
/* eslint-disable jsx-a11y/anchor-is-valid */
import React from 'react';
import { useNavigate } from 'react-router-dom';
import styled from 'styled-components';
import WithDashboardNavigate from '../../session/WithDashboardNavigate';
function SideMenu(props) {
const { close, dashboardNavigater } = props;
const navigate = useNavigate();
const onProfilePageClick = () => {
if (close) close();
dashboardNavigater(navigate);
};
return (
<div>
<MenuLinksSpace />
<MenuLinks>
<li>
<a onClick={onProfilePageClick} role="presentation">
<span className="icon is-medium">
<i className="fas fa-user" />
</span>{' '}
Dashboard
</a>
</li>
</MenuLinks>
</div>
);
}
My question is I'm I overdoing this? I mean is there an easier way to do this conforming better to React best praxis?
Upvotes: 1
Views: 55
Reputation: 10071
It's totally dependent on the requirement and how you design. My opinion is that if you using function components you don't need to mix with class components and bind(this).
Note: WithDashboard function you are not passing props if any component passes props that are not passed to WithDashboardBase.
import React from 'react';
import AuthUserContext from './context';
import * as ROLES from '../constants/roles';
const WithDashboardNavigate = Component => {
const WithDashboardBase = (props) => {
const onDashboard = navigate => {
const { authUser } = props;
if (authUser) {
if (authUser.roles.includes(ROLES.ANON)) {
navigate('/app/login');
} else if (authUser.roles.includes(ROLES.USER) || authUser.roles.includes(ROLES.ADMIN)) {
const view = localStorage.getItem('currentDashBoardView');
// Here if user has used nav menu earlier then that last view is loaded
if (view) navigate(view);
// or default to dash
else navigate('/app/dashboard');
}
}
};
return <Component dashboardNavigater={onDashboard} {...props} />;
}
const WithDashboard = (props) => ( // Pass props from here as well
<AuthUserContext.Consumer>
{authUser => (
<div>
<WithDashboardBase authUser={authUser} {...props} />
</div>
)}
</AuthUserContext.Consumer>
);
return WithDashboard;
};
export default WithDashboardNavigate;
I have created connect HOC for context API(same as redux). Check this it'll help you understand props pass from parent to child.
https://stackblitz.com/edit/reactjs-usecontext-usereducer-state-management?file=src%2FStore.js
Upvotes: 3