Can I pass data fetched in getStaticProps to a component? [duplicate] - reactjs

This question already has answers here:
React 18: Hydration failed because the initial UI does not match what was rendered on the server
(43 answers)
Closed 4 months ago.
My getstaticProps:
export async function getStaticProps({ params }) {
const mainMenuData = await fetch(
`https://example.com/get/main-menu`
).then((res) => res.json());
return {
props: {
mainMenuData,
},
revalidate: 60,
};
}
Using the component:
<Header data={mainMenuData} />
My component:
export default function Header({ data }) {
return (
<>
{data.main_menu}
</>
);
}
The data is an object, and I can access it so technically I know it's possible. However when I start mapping through the data I keep getting the error:
Hydration failed because the initial UI does not match what was rendered on the server
I'm new to Next and I'm not sure this method is correct.
Edit: Page component
import Head from "next/head";
import styles from "../styles/Home.module.css";
import Header from "../components/header";
export default function Page({ mainMenuData }) {
return (
<div className={styles.container}>
<Head>
<title>Create Next App</title>
<meta name="description" content="Generated by create next app" />
<link rel="icon" href="/favicon.ico" />
</Head>
<main className={styles.main}>
<Header data={mainMenuData} />
</main>
</div>
);
}
export async function getStaticProps({ params }) {
const mainMenuData = await fetch(
`https://example.com/get/main-menu`
).then((res) => res.json());
return {
props: {
mainMenuData,
},
revalidate: 60,
};
}

This error might be happening due to not wrapping the data you are passing to Header properly in a JSX element. Try using a JSX element inside of Header like a div or ul if it's a list for example.
Also, avoid some JSX wrapping patterns such as, for example, a p tag wrapping up a div, section, etc. Next.js will most likely throw a similar error because of this.
Reference thread

Related

Next.js > How to Implement Dynamic Route Based Modals

Is it possible to implement a dynamic route based modal in Next.js 13 (using the app directory) ?
For reference, I'm aiming to create a similar flow to how the homepage of nomadlist (and instagram) is, such that when you click on a card, a modal appears with the updated route, i.e. https://nomadlist.com/madeira, and when visiting the link link directly, you are taken to the full page.
I am also adding the list items that have modal's to my app's root directory, and I would like to have the modal route URL nested like: /users/[userId]
What I need to do is this:
When triggering the modal in my app's list view, update the current URL without refreshing the browser. (i.e. using a State / context to trigger the modal). i.e. /users/[userId]
When visiting the modal's route directly, i.e. /users/123-43249, to display a full page of the user.
I've tried a bunch of different things, but can't seem to get this to work, so I'm more curious if this is even possible before spending more time on it.
The current structure of my app is this:
// layout.tsx
export default async function RootLayout({ children }) {
return(
<html>
<head />
<body>
<ProfileModalProvider>
{children}
</ProfileModalProvider>
</body>
</html>
)
}
// page.tsx
export default async function Home() {
const users = await getUsers();
return (
<main>
<Hero />
<SearchSection />
<UserList users={users} />
<ProfileModal /> // Should I import the whole page from '/users/[userId] here?
</main>
);
}
// ViewUserModalButton.tsx (comes from the UserList.tsx)
export default function ViewProfileButton({ user }: { user: IUser }) {
return (
<Link
as={`/users/${user.id}`}
href={{
pathname: "/users/[userId]",
query: { userId: user.id },
}}
scroll={false}
shallow={true}
>
<div>
View User
</div>
</Link>
);
}
Thank you so much.
The only way I was able to implement this was to override the default behavior of the open modal function and append URL to the window's history.
const [{ shouldShowModal }, setShouldShowModal] = useProfileModal();
const toggleModal = e => {
e.preventDefault();
setShouldShowModal({ shouldShowModal: true, profile });
window.history.pushState({}, "", `/users/${profile.id}`);
}
export default function ViewProfileButton({ user }: { user: IUser }) {
return (
<Link
as={`/users/${user.id}`}
href={{
pathname: "/users/[userId]",
query: { userId: user.id },
}}
scroll={false}
shallow={true}
onClick={toggleModal}
>
<div>
View User
</div>
</Link>
);
}

Using react context not working as expected in remix react?

Despite having seen working examples of this in non remix projects, it doesn't seem to work in the way I'm implementing it?
I have the following in root.tsx:
export const MyContext = createContext("default");
function Document({ children }: { children: React.ReactNode }) {
return (
<html lang="en">
<head>
<Meta />
<Links />
</head>
<body className="root-body">
<MyContext.Provider value="bonjour!">
<Header />
</MyContext.Provider>
{children}
<ScrollRestoration />
<Scripts />
<LiveReload />
<Footer />
</body>
</html>
);
}
export default function App() {
return (
<Document>
<Outlet />
</Document>
);
}
In my <Header/> component I have:
import { useContext } from "react";
import { MyContext } from "~/root";
export const Header = () => {
const result = useContext(MyContext);
console.log(result);
return(null)
}
The result is then that "default" is printed to the console, but surely from my understanding it should be "bonjour"?
Where am I going wrong?
The output on the server console is from Remix SSR. It does appear that the context is not being applied during server rendering. However, it does show up correctly after hydration. Unfortunately it also results in hydration errors (see browser console).
Anyway, that does seem odd. My understanding is that you can use most hooks server side (except for useEffect and useLayoutEffect).
https://codesandbox.io/s/remix-react-context-mzexmt

TypeError: Cannot read property 'map' of undefined, not working even with different api's and variable definitions

im creating a restuarant pos and after passing the props into a seperate component which i use to map data from the api to the html cards, i continuously encounter this error. im using the axios api and it works fine as it displays all the data on the console.log. the initial error i had was o do with the axios api which i believe i fixed but this map function error does not change even when i use other api methods such as fetch.
import styles from "../styles/foodlist.module.css"
import Foodcard from "../components/foodcard"
const Foodlist = ({foodlist}) =>{
return(
<div className={styles.container}>
<h1 className={styles.title}>Popular food</h1>
<div className={styles.wrapper}>
{foodlist.map(food => {
return(
<Foodlist key={food._id} food = {food}/>
)
})}
</div>
</div>
)
}
export default Foodlist
the above code is what produces the error: "TypeError: Cannot read property 'map' of undefined".
the code below is where i defined the prop foodlist
import Head from 'next/head'
import Image from 'next/image'
import Foodlist from '../components/foodlist'
import Welcome from '../components/Welcome'
import styles from '../styles/Home.module.css'
import axios from "axios"
export default function Home({foodlist}) {
console.log('foodlist', foodlist)
// console.log(axios)
return (
<div className={styles.container}>
<Head>
<title>Emilia Plate</title>
<meta name="description" content="Emilia plate, order and pay for any meal offered on our menu" />
<link rel="icon" href="/favicon.ico" />
</Head>
<Welcome/>
<Foodlist foodlist = {foodlist}/>
</div>
)
}
export const getServerSideProps = async () => {
const res = await axios.get("http://localhost:3000/api/products");
// const data = await res.json();
return{
props:{
foodlist: res.data,
}
}
}
when i place the ? in the map function it displays popular foods (the title) several times instead of placing the data that it should map

react storefront TypeError: Cannot read property '_includeAppData' of undefined

I have been using react storefront for a couple of weeks now. Though I understood high level concepts, I am really stuck for API implementation using fulfillAPIRequest, fetchFromAPI, appData and pageData etc.
My current code is as follows:
File: _app.js:
export default function MyApp({ Component, pageProps }) {
useJssStyles()
const classes = useStyles()
const [appData] = useAppStore(pageProps || {})
return (
<PWA errorReporter={reportError}>
<Head>
{/* <meta
key="viewport"
name="viewport"
content="minimum-scale=1, initial-scale=1, width=device-width, shrink-to-fit=no"
/> */}
</Head>
<SessionProvider url="/api/session">
<MuiThemeProvider theme={theme}>
<CssBaseline/>
<Header className={classes.header} />
<HeaderBanner />
<Delivery />
<Search />
<main className={classes.main}>
<Component {...pageProps} />
</main>
<Footer />
</MuiThemeProvider>
</SessionProvider>
</PWA>
)
}
MyApp.getInitialProps = async function({ Component, ctx }) {
let pageProps = {}
if (Component.getInitialProps) {
console.info("Executing _app.js: Invoking Component.getInitialProps...")
pageProps = await Component.getInitialProps(ctx)
}
return { pageProps }
}
file: pages/index.js => entry point page
import React from 'react'
import { fetchFromAPI, createLazyProps } from 'react-storefront/props'
import NearbyShops from '../components/shops/nearby-shops.js'
export default function Index(lazyProps) {
return (
<NearbyShops />
)
}
Index.getInitialProps = createLazyProps(fetchFromAPI, { timeout: 50 })
I implemented api for the page index.js, in the foder /pages/api/index.js, as follows...
import fulfillApiRequest from 'react-storefront/props/fulfillAPIRequest'
function getPageData () {
console.info("Executing 'getPageData' in /api/index.js...")
return Promise.resolve({})
}
export default async function Index (params, req, res) {
console.info("Executing '/pages/api/index.js' ...")
const result = await fulfillApiRequest(req, {
appData: () => getAppData(),
pageData: () => getPageData()
})
return result
}
When I run this app, I get the following error in the GUI:
In the console, I get the error stack trace as follows...
If I don't use the fulfillAPIRequest and its related api methods, I am able to show the rendered page, normally. But now I want to integrate the API. The official documentation is not that helpful in this regard.
Please help.

Stripe not initialized

i decided to use nextjs with stripe and did it like this, but i get the error Error: Please pass a valid Stripe object to StripeProvider. You can obtain a Stripe object by calling 'Stripe(...)' with your publishable key.
i am passing a stripe object but weirdly enough it doesnt go through and even when trying to console.log in next.js its not showing in console. So what am i doing wrong? Thanks
function MyApp({ Component, pageProps }) {
const [stripe, setStripe] = useState({ stripe: null });
useEffect(() => {
console.log("djdsjdjsd");
if (window.Stripe) {
setStripe({ stripe: window.Stripe('pk_test') });
} else {
document.querySelector('#stripe-js').addEventListener('load', () => {
// Create Stripe instance once Stripe.js loads
setStripe({ stripe: window.Stripe('pk_test') });
});
}
}, []);
return (
<>
<Head>
<title>My page title</title>
<meta property="og:title" content="My page title" key="title" />
<script async src="https://js.stripe.com/v3/"></script>
</Head>
<StripeProvider stripe={stripe}>
<Component {...pageProps} />
</StripeProvider>
</>
)
}
Instead of trying to build your component around Stripe.js loading like this, you should use the loadStripe helper from #stripe/stripe-js with the Elements provider from #stripe/react-stripe-js. This will handle loading Stripe.js for you asynchronously along with the initialization.
Docs
Example:
import {Elements} from '#stripe/react-stripe-js';
import {loadStripe} from '#stripe/stripe-js';
const stripePromise = loadStripe('pk_test_123');
const App = () => {
return (
<Elements stripe={stripePromise}>
<PaymentComponentWithCardElementEtc />
</Elements>
);
};

Resources