I started a project with next js and typescript. I have a main component that I call it in the index.js page I use the getStaticProps function in the main component getStaticProps returns a prop object and when I log this prop in my main component I received undefined in my console.
I want to know using the getStaticProps in the component is wrong and I have just to use that function in pages or not.
I am a newbie in next js and I would be very grateful if anyone could help me.
this is my main component
import React from 'react';
import {IMain} from "../../../../interfaces/components/IMenu/IMain";
const Main:React.FC<IMain> = (props) => {
console.log(props);
return (
<div>
</div>
);
};
export async function getServerSideProps() {
return {
props: {
data: 'ggwp'
}
};
}
export default Main;
and this is my index.js page
import Text from "./../components/ui/Text/Text";
import Button from "../components/ui/Button/Button";
import Main from "../components/Menu/Desktop/Main/Main";
const Home = () => {
return <Main/>;
};
export default Home;
getStaticProps can only be exported from a page. You can’t export it from non-page files.It will not work if you add getStaticProps as a property of the page component.
https://nextjs.org/docs/basic-features/data-fetching
Here's a possible solution:
Using a node script (like predev) to fetch your content and store it in JSON files in your project, then reference those JSON files in your component.
Posted about it here:
https://dev.to/brewhousedigital/nextjs-getstaticprops-with-components-f25
Solution
used react's useEffect() for component
and for page getStaticProps() of next.js
after combine the two will have hybrid page
Related
Suppose my URL looks something like this:
/blog/[post_id]/something
What is the recommended way to pass $post_id down to any component anywhere in the tree?
I know how to retrieve route parameters using getInitialProps but passing the values down is always giving me a hard time.
For pages I could technically use React Contexts although this seems a bit oversized for such a trivial use case.
For layouts I am honestly completely lost because pages are children of layouts and the return value of getInitialProps is passed to the page and not the layout.
My components could make use of useRouter but this requires useEffect and would also make my component depend on the route itself...
Any advice would be welcome (:
My components could make use of useRouter but this requires useEffect and would also make my component depend on the route itself...
useRouter seems like the obvious solution here. I'm not exactly understanding your concerns regarding the component depending on the route. I guess it does make the Layout less flexible since it needs to know that the post id is stored in the post_id query variable. But I would do it anyways :) It gives you a nice and simple way to access the query variables which can be used in a Layout that's outside of your BlogPost or in a deeply-nested component that you use inside the BlogPost.
Using the per-page layouts approach:
/components/Layout
import { useRouter } from "next/router";
import { ReactNode } from "react";
export default function Layout({ children }: { children: ReactNode }) {
const router = useRouter();
return (
<div>
<h3>You are viewing post id #{router.query.post_id}</h3>
{children}
</div>
);
}
/pages/blog/[post_id].jsx
import Layout from '../../components/Layout';
export default function BlogPost() {
return <div>Hello World</div>
}
BlogPost.getLayout = function getLayout(page) {
return (
<Layout>
{page}
</Layout>
)
}
/pages/_app.tsx (to support per-page layouts, copied from docs)
export default function MyApp({ Component, pageProps }) {
// Use the layout defined at the page level, if available
const getLayout = Component.getLayout || ((page) => page)
return getLayout(<Component {...pageProps} />)
}
I think the easiest and the cleanest way is to use window.location.pathname. this will give you the part after the domain name. for example for
http://localhost:3001/blog/[post_id]/something
you will get /blog/[post_id]/something
const pathname=window.location.pathname
const splittedPathname=pathname.split("/") // ['', 'blog', '[post_id]', 'something']
const dynamicId=splittedPathname[2]
you can run above code in useEffect and set a state. or you could write a hook and use it in the components that under dynamicId components
import React, { useState, useEffect } from "react";
const usePathname = () => {
const [postId, setPostId] = useState("");
useEffect(() => {
const pathname = window.location.pathname;
const splittedPathname = pathname.split("/");
const dynamicId = splittedPathname[2];
setPostId(dynamicId);
}, []);
return { postId };
};
export default usePathname;
If you are looking for client side rendering, useRouter is the best way to go. If you are looking for SSR or SSG, you should rather use getStaticProps or getServerSideProps.
I want to integrate a module that only support server side rendering. This is project structure.
index.js
view.js
part.js (Class component)
I can use the module in getServerSideProps method in index.js. But I want to use it in part.js since there are some content I need to pass to the module that are available in part.js.
I've tried to pass a function in getServerSideProps as a prop to the component but it doesn't allowed.
Can I run server side rendering code in react class component?
server side rendering just working on pages/ directory , you cant use it in component or ....
if you want to use It on pages/ files and its not working check 2 thing
if you have _app.jsx in your project or not
if you have __app.jsx you should define it right like this
import App from 'next/app';
const MyApp = ({ Component, pageProps }) => {
return (
<Component {...pageProps} />
);
};
MyApp.getInitialProps = async (appContext) => {
const { pageProps } = await App.getInitialProps(appContext);
const { ctx } = appContext;
return { pageProps};
};
export default MyApp;
I'm going through this article and I'm trying to figure out how the persistence is supposed to occur in Option 4. From what I can tell, you'd need to redefine the .getLayout for every page. I'm not sure how the logic for nesting is incorporated into further urls.
Here's the code from the article
// /pages/account-settings/basic-information.js
import SiteLayout from '../../components/SiteLayout'
import AccountSettingsLayout from '../../components/AccountSettingsLayout'
const AccountSettingsBasicInformation = () => <div>{/* ... */}</div>
AccountSettingsBasicInformation.getLayout = page => (
<SiteLayout>
<AccountSettingsLayout>{page}</AccountSettingsLayout>
</SiteLayout>
)
export default AccountSettingsBasicInformation
// /pages/_app.js
import React from 'react'
import App from 'next/app'
class MyApp extends App {
render() {
const { Component, pageProps, router } = this.props
const getLayout = Component.getLayout || (page => page)
return getLayout(<Component {...pageProps}></Component>)
}
}
export default MyApp
For example, say AccountSettingsBasicInformation.getLayout is /settings/, how would I use this template to produce something at /settings/username
P.S. If someone has done something in the past they'd recommend over this, I'm open to ideas.
Yes, you have to redefine the getLayout function to every page. As long as the SiteLayout component stays “unchanged” (eg.no props change) the rendered content in that layout component (not the page content itself) stays persistent. This is because React wont rerender that component.
I used Adam’s article when I was building next.js lib for handlin modal routes. You can check the example folder where you can see I am defining the getLayout property on every page which should be rendered with layout.
Example: https://github.com/svobik7/next-bodies/tree/master/example
I would like to refactor my Next.js webapp to have different pages handle different screens. Currently, I have this component holding several states to know in which screen I'm in. In the jsx section, I'm using {value && ... } to render the right component.
But I feel this is not good design, and won't be maintainable when adding more and more screens.
I would also like to avoid Redux as it is overkill for my project.
I was thinking about persisting data in cookies so I can retrieve them with getInitialProps in every component when rendering a new page, but is there a more elegant way?
I've read about tweaking the _app.js but I'm not sure to understand the consequences of doing so, and how it could help me..
Any suggestion?
When multiple of your pages need to make use of same data, you can make use of Context to store the result. It a good way to make a centralized storage without using complex and more self sufficient libraries like redux
You can implement context inside of _app.js file which must reside inside your root folder. This way next.js treats it as a root wrapper and you would just need to use 1 instance of Context
contexts/appContext
import React from 'react';
const AppContext = React.createContext();
export const AppProvider = AppContext.Provider;
export const AppConsumer = AppContext.Consumer;
export default AppContext;
_app.js
import React from 'react'
import App from 'next/app'
import AppProvider from '../contexts/appContext';
class MyApp extends App {
state={
data:[]
}
render() {
const { Component, pageProps } = this.props;
// You can implement logic in this component to fetch data and update state
return (
<div>
<AppProvider value={this.state.data}> // pass on value to context
<Component {...pageProps} />
</AppProvider>
</div>
)
}
}
export default MyApp
Now further each component can make use of context value by using AppConsumer or using useContext if you use hooks
Please read more about how to use Context here
Hi guys hope you're fine, I'm student and I have this year to do some thing like a project to end my studies , so I chose to create a website (using React/Django) I already have the site but made by HTML,CSS,bootstrap & JQuery , so now i have to convert it to react , but i have a problem i don't know how to include some js files inside a components , every things else is going good, I need just what is in the js files to applied it in some components.
Hope you help me out.
cordially
You can have javascript code inside your components likewise
const Component = props => {
//javascript code
return (<div>-- Component JSX---</div>)
}
if the javascript code if just needed for the initializing of the component you can use react hooks to run a piece of code only one time after the component is created.
import React, { useEffect } from 'react';
const Component = props => {
useEffect(() => {
// javascript code
}, [])
return (<div>--Component JSX---</div>
}
the empty array as second argument indicates the useEffect hook that the effect should only be ran once after the component has been initialized.
So the way React works is you will be building "HTML" using React functional/class components like this example
import React from 'react';
//Just like a normal javascript function, it listens to in this
instance, the return statement. You're returning regular HTML.
function Navbar() {
return (
<div>This is some text built by react</div>
<p>Saying hello to react by building a functional component</p>
)
}
export default Navbar; //This right here is exporting the file so it can be
//used elsewhere just import it in other file.
So the return is where you will build your website, then in the next component you will import should look something like this.
Normally, it is called App.js or in some instances where it's more complex it's anythinng you want.
import Navbar from '../components/Navbar.js';
function App() {
return (
<Navbar /> //Now you don't have to write your main content in here you can
//just import it. Just like Navbar
<div>This is my main content in page</div>
)
}