Ways of creating reusable header with react - reactjs

I am new in react and I am searching the best way for creating a reusable header.
The goals is to reuse a header component in multiple apps by passing somes properties such as:
- Main Title
- Logo
- String List of menus and route paths for render multiple buttons menus for the navigation
- And a boolean for a last button menus for administration
Finally the signature exemple of the component would be something like:
<Header title="title" menus_json=[{'title':'tab1', 'route_path'='/tab1'},...] logo_path=[] admin=False />
How can we achieve that ? Any suggestion, documentation for that ?

You can create a Header component and pass dynamically to every component where needed by values.
Header.js
function Header({title,menus_json,logo_path,admin}){
return (
<header>
// use your title,menus_json,logo_path,admin
</header>
)
}
Use like this in needed components - example
Component1.js
function Component1(){
return (
<div>
<Header title="title" logo_path=[] admin=False
menus_json=[{'title':'tab1', 'route_path'='/tab1'}] />
<div>...</div>
</div>
)
}
Component2.js with different values title,menus_json...etc.
function Component2(){
return (
<div>
<Header title="title2" logo_path=[] admin=False
menus_json=[{'title':'tab2', 'route_path'='/tab2'}] />
<div>...</div>
</div>
)
}

Related

Reactjs component - one vs many

I'm new to react and I'm trying to figure out the best way to make a component that can handle different scenarios. I'm not sure if the best practice would be to make multiple components or one component to handle it all.
Imagine a frontpage were you have 3 different entrances like recent products, blogpost or Instagram pictured. Each entrance use a component called featured and inside that component I should render either products, blogpost or Instagram pictures. Everything for the layout is the same, its just the items in the grid that needs to change. What would be the best way to solve this? one component with 3 different sub-components or 3 components with one for each type.
I know how to make 3 different components, but I'm not sure how to make one component to handle subcomponents.
This could be the component and the "grid-item--product" could also be a "grid-item--blogpost or "grid-item--Instagram" - "grid" could also be a "two-col" or "three-col".
<div className="featured">
<div className="featured--content">
<div className="grid four-col">
<grid-item--product />
</div>
</div>
</div>
and this could be where I would call the component and hopefully be able to handle which component should be rendered inside and what the grid should be for this feature.
<div className="frontpage-route">
<h2>Frontpage Route</h2>
<Featured />
</div>
Can you help me? I would love an example if possible.
Thanks.
It sounds like what you want is the children prop. You can add the children prop to Featured and just pass the correct children to it. See an example here:
const Featured = ({ children, numColumns = "one" }) => (
<div className="featured">
<div className="featured--content">
<div className={`grid ${numColumns}-col`}>
{children}
</div>
</div>
</div>
)
const App = () => (
<div className="frontpage-route">
<h1>Frontpage Route</h1>
<h2>Products</h2>
<Featured numColumns="two">
<grid-item--product />
<grid-item--product />
</Featured>
<h2>Blogs</h2>
<Featured numColumns="three">
<grid-item--blog />
<grid-item--blog />
</Featured>
<h2>Instagram</h2>
<Featured>
<grid-item--instagram />
<grid-item--instagram />
</Featured>
</div>
)
You can use consitional rendering and three boolean variables to display components.
e.g:
<div className="featured">
<div className="featured--content">
<div className="grid four-col">
{product && <grid-item--product />} //if product var is true this component renders
{blogpost && <grid-item--blogpost />} //if blogpost var is true this component renders
{instagram && <grid-item--instagram />} //if instagram var is true this component renders
</div>
</div>
</div>

Load content from sidebar in react

I found this template of react sidebar which I have implemented successfully. However, I am stuck on how to load the content.
<SubMenu
title="Users"
icon={faBriefcase}
items={["Create", "List"]}
/>
How do I route the content I want to show when a menu item is selected? (either Create or List in the example above)
As React provides with Link Tags to Route.
Do it like this. Your items should be wrapped in a Link tag to route.
<SubMenu
title="Users"
icon={faBriefcase}
items={[
<Link to"path">"Create"</Link>,
<Link to"path">"List"</Link>
]}
/>
As per your comment you need something like this
<Layout>
<App/>
</Layout>
Whereas Layout is
const Layout = ({children}) => {
return(
<>
<Appbar />
<Sidebar />
<main>
{children} // your whole app renders here
</main>
</>
)
}
export default Layout;
You could add a .sidenavactive class to main tag that becomes active when side bar is opened so you adjust or push page content using .sidenavactive.
Now when you will change route in Sidebar items. Just the main content will change.

Material UI. Show different components depending on breakpoints (SSR)

On small devices (phones) I want to show <Foo/> component and on large (desktops) <Bar/>, like this
function MyComp (props) {
if (isMobile)
return <Foo/>
else
return <Bar/>
}
}
I could find only 2 possible ways to implement it in Material UI :
Using Hidden component
Using withWidth HOC
Option with HOC seemed to me more correct in this case, but apparently it doesn't work correctly with SSR (but Hidden does).
So is it OK in terms of best practices to use two Hidden elems? Like this:
function MyComp (props) {
return (
<>
<Hidden mdUp implementation="css">
<Foo/>
</Hiddne>
<Hidden smDown implementation="css">
<Bar/>
</Hidden>
</>
)
}
There is no problem in using <Hidden /> like that, it just adds a <div> with the necessary CSS to show or not your component. A better approach though would be to add a CSS class directly to your <Foo /> and <Bar /> components, to avoid extra <div> in your page, like this:
function MyComp (props) {
return (
<>
<Foo className={props.classes.foo} />
<Bar className={props.classes.bar} />
</>
)
}
The implementation="css" is necessary in SSR setups because the JS implementation may "flash" the component on the page, then remove it when JS has loaded. The downside of the CSS implementation is that the element is kept in the DOM.
PS: withWidth will be deprecated.

Passing components into another in react

I have an app with a number of components. One of the components I need be to able to pass different variations of another two components into, based on a layout. I believe it can be passed in like a data attribute, but I'm unsure of the exact syntax to push the other components in.
Given two components <List /> and <Box /> which are currently in another component being imported into my main App.js file as such:
export const CallOut = () => {
return(
<div style={styles.sectionInner}>
<List />
<BoxRight/>
</div>
)
};
where <CallOut /> is being imported into App.js, I'd like to pass those two components into the <CallOut /> component.
What is the correct syntax to pass those two in and have them placed in the same spot they're currently in within the CallOut component?
I believe it should be something similar to
<CallOut param={List} param={BoxRight} />
but I know this isn't right.
You can use capital names for props, and use these to instantiate react components like this:
export const CallOut = ({List, Box}) => (
<div style={styles.sectionInner}>
<List/>
<Box/>
</div>
);
List and Box are the properties of this component. You can instantiate it like this:
<CallOut List={SomeComponent} Box={SomeOtherComponent}/>
I don't know if we're on the same page but maybe you're looking for children property ?
So your component will look like that:
export const CallOut = ({children}) => (
<div style={styles.sectionInner}>
{children}
</div>
);
And usage:
<CallOut >
<List/>
<Box/>
</CallOut>
You can pass any component as CallOut child or even do some filtering using children API
It's common usage when components don’t know their children ahead of time and it's used just for some kind of boxing/wrapping.

Set state property from URL using react-router

I have a container component with a modal in it that is opened and closed based on a state property.
I want to control this via the URL, i.e. I want to have
/projects - the modal is NOT open
/projects/add - the modal IS open
As well as being able to link directly to it, I want the URL to change when I click on links within the main container to open the modal.
Can someone explain how I could do this, or point me in the right direction of a good tutorial?
NOTE: This way is not perfect. Even more it's rather antipattern than pattern. The reason I publish it here is it works fine for me and I like the way I can add modals (I can add modal to any page and in general their components don't depends on the other app in any way. And I keep nice url's instead of ugly ?modal=login-form). But be ready to get problems before you find everything working. Think twice!
Let's consider you want following url's:
/users to show <Users /> component
/users/login to show <Users /> component and <Login /> modal over it
You want Login to not depend on Users in anyway, say adding login modal to other pages without pain.
Let's consider you have kinda root component which stands on top of other components. For example Users render may look something like this:
render() {
return (
<Layout>
<UsersList />
</Layout>
);
}
And Layout's render may look something like this:
render() {
return (
<div className="page-wrapper">
<Header />
<Content>
{this.props.children}
</Content>
<Footer />
</div>
);
}
The trick is to force modal's injection to <Layout /> every time we need it.
The most simple approach is to use flux for it. I'm using redux and have ui reducer for such page meta-information, you can create ui store if you use other flux implementation. Anyway, final goal is to render modal if <Layout />'s state (or even better props) contains modal equal to some string representing modal name. Something like:
render() {
return (
<div className="page-wrapper">
<Header />
<Content>
{this.props.children}
</Content>
{this.props.modal ?
<Modal key={this.props.modal} /> :
null
}
<Footer />
</div>
);
}
<Modal /> returns modal component depends on given key (In case of our login-form key we want to receive <Login /> component).
Okay, let's go to router. Consider following code snippet.
const modal = (key) => {
return class extends React.Component {
static displayName = "ModalWrapper";
componentWillMount() {
// this is redux code that adds modal to ui store. Replace it with your's flux
store.dispatch(uiActions.setModal(key));
}
componentWillUnmount() {
store.dispatch(uiActions.unsetModal());
}
render() {
return (
<div className="Next">{this.props.children}</div>
);
}
}
};
...
<Route path="users" component={Next}>
<IndexRoute component={Users}>
<Route path="login" component={modal('login-form')}>
<IndexRoute component={Users} />
</Route>
</Route>
(Don't care about Next - I add it here for simplicity. Imagine it just renders this.props.children)
modal() function returns react component that triggers change in ui store. So as soon as router gets /users/login it adds login-form to ui store, <Layout /> get it as prop (or state) and renders <Modal /> which renders corresponding for given key modal.
To programmatically assess to a new URL, pass the router to your component and use push. push for example will be call in the callback trigger by the user action.
When setting your router set a route to /projects/:status. then, in your component route, you can read the value of status using this.props.param.status. Read "whats-it-look-lik" from react-router for an example.

Resources