How to add a list of global components in nextjs - reactjs

I'm new in Nextjs and I want to add a list of components and utilities to all of my pages in Nextjs. How can I make them all available in my components without importing them one by one.
Also some utilities might be needed in getInitialProps function in pages like axios or in my case client of Apollo.
I don't expect some one write me a whole config file for Nextjs.config just help me to understand the configuration of next deeper.
thanks in advance

I would suggest to do dynamic import on each page, for each component and utility instead of making components global. By doing so Next.js will create a small chunks or "pages" without any unused components.
If you load components globally, every page would increase in size but actually not use these components or utilities. It defeats a purpose of code-splitting.
It breaks modularity of your code, because components/pages (modules) will depend on some global utilities implicitly.
If you have too many imports in your component or page, probably, it's a sign to encapsulate that extra functionality by extracting it to it's own component.
Controversially, you could try to add global utilities in Custom "App"
For example, you could pass a React component to all Next.js pages via props of custom App.
_app.js
import Icon from '../components/Icon';
export default function MyApp({ Component, pageProps }) {
return <Component {...pageProps} icon={Icon} />
}
As all pages are instancing from the App, every page would have this component in the props.
index.js
const Home = props => (
<div>
<props.icon><props.icon/>
</div>
);
If you have many components you could group them into list and assign to a single prop, so you can use it like:
index.js
const Home = props => (
<div>
<props.components.icon/>
<props.components.anotherIcon/>
</div>
);
On a side note, it's suggested to use getStaticProps and getServerSideProps for pages instead of getInitialProps since Next.js 9.3.
Suggested reading:
Next.js Data fetching (getInitialProps)
React.js Code-Splitting

Related

Navigation links server side rendering in nextjs

i'm still new to nextjs and i'm building static site, i'm trying to make server responsible for rendering navigation links but i can't figure this yet how to do this and how to fetch those links
as you know navigation links lies in seperate component and not included in every page and also fetching data must be in nextPage not in the components
the only solution i have is to fetch navigation links when home page loads and then get the navigation links as props and pass it the context but this will make the client responsible for rendering the naviagtion
my _app.js is
import '../styles/globals.scss'
import { Layout } from '../components'
function MyApp({ Component, pageProps }) {
return (
<Layout>
<Component {...pageProps} />
</Layout>
)
}
export default MyApp
as you see the Layout contains the navigation and Component has the rest
The global data should come from the layout, not from the page. If you have more than one page, you don't want to repeat your API calls in each pages.
If you use the nextjs 13 (still in beta atm), you can do this in the app/ directory. If you don't, you will need to use useSwr in your layout : https://nextjs.org/docs/basic-features/layouts.
To summarize, if you really want to be client agnostic on this feature, i think you need to try nextjs 13.

How do I change the styles of some shared component in React and I have configured routes with react route

I am working on a web app that is consisted of few pages and have configured routes with react-route-dom. On the pages, I have some shared components and I want them to be styled differently on other pages except the Home page.
How do I get this done? Any help?
Thanks
Check if pathname is path of home or else not you can use useLocation to get the pathname and add conditional styling or classes.
useLocation v5
useLocation v6
import React from 'react';
import {useLocation} from 'react-router-dom';
export const Common_Component=()=>{
const location=useLocation()
const pathname=location.pathname
return(
<div>
<div classes={pathname=="home"?"home_class":"other_class"}>
...
</div>
</div>
)
}
Or
You can pass boolean props to the component to let component know it should use home bases classes or other classes.
PS.
you will still need to do conditional check if props is true or false
useMatch you can use useMatch to match the current url with regex.
While it is always good to share code, I would recommend creating a new component for the homepage. Otherwise you are coupling your components. What happens if you want to add another specialisation for the whatever-component? You add another case! Your components grow and wire up more and more until you have one big pot of spaghetti. Hence, it makes sense in many situations to just create a new component for a new use-case.

Is there a way to pass state to pages in Gatsby?

Since Gatsby effectively hides the router, you can't pass props to each page in the way you would with BrowserRouter in Create-React-App. Is there a way to do this in Gatsby? I assume I need to do it somehow in Gatsby-browser.js. I basically want to maintain a state called Step, that is accessible by all pages. Would I have to use Context for this?
You can pass state into a page with Link (docs), but be mindful of pages being built without state (i.e. statically).
<Link
to={`/photos/`}
state={{ tag }}
>
See more {tag}
</Link>
const PhotosPage = ({ location: { state } }) =>
<div>{state?.tag ? `${tag} photos` : "All photos"}</div>
The native (and easiest) way is using React context but you have multiple ways of sharing a global state in Gatsby:
Using global wrappers within the wrapRootElement exposed API:
import React from "react"
import { ThemeProvider } from "./src/context/ThemeContext"
export const wrapRootElement = ({ element }) => (
<ThemeProvider>{element}</ThemeProvider>
)
If you follow this approach, you'll need to use wrapRootElement in both gatsby-browser.js as well gatsby-ssr.js since it's a shared API.
Keep in mind that Gatsby's router extends from #reach/router (from React).
In that way, you'll keep your step state across the application.

Material UI Styles issue with Single-SPA

I am using single spa to create a my react microfrontends, in one of the MFE(microfrontend) I need to dynamically import a ".js" from another MFE and render the component , for that I am using systemjs import
Below is a sample code on how the child component exposes a function to export a js file in the main files
export function getcode() {
return import("./views/rk.js");
}
and in the parent component I use react.lazy to import the js file from the function and render as component
const Test = React.lazy(() =>
import("#Test/react-singlespa").then((mod) => mod.getcode())
);
and render the above const as below using
<React.Suspense fallback="Loading ...">
<Test/>
</React.Suspense>
I don't have issue while running the code in development mode but in the production mode the styles are messed up for first load but subsequently the styles are fine.
The question seems to be common with material ui issues import of webpack, but none of the solutions online seem to help. I tried every possible solution given in the below links
https://github.com/mui-org/material-ui/issues/15610
https://material-ui.com/getting-started/faq/#i-have-several-instances-of-styles-on-the-page
Assuming this is something that has to be done with Single-spa framework ...any help in this regard is greatly appreciated

Fetch data for the entire app without depending on component logic

There are X routes in the frontend made with React-router and each of them drives to a component.
No matter which route is visited, I need to use some data from an api.
This data is constant through the application. Using Redux I could dispatch an action FETCH_DATA in each React component and manage the logic of fetching in Redux actions.
However, this looks repetitive to me because I would be writing the same logic through all the React components that need data: look for the the data in the store. If it's there take it. If it's not there, dispatch FETCH_DATA.
What is another approach?
You can call that api in the App.tsx i.e. your first component to be rendered in the application. This is the component which actually holds the Routes also.
Consider the following code as an example and change it according to the need of your application:
class App extends React.Component {
ComponentDidMount() {
this.props.callTheApiHere()
}
render() {
return (
<Routes history={this.props.history} />
)
}
}
export default App;
Now each component that any of your Route render have to just get the data from the redux store using mapStateToProps in react-redux Connect
GraphQL offers an elegant solution for this requirement of sharing data across components belonging to different routes.
More information:
https://www.youtube.com/watch?v=p_kqcGW1jkY
Apollo GraphQL (React) Data sharing across components

Resources