Using Next.js to Retrieve JSON Data and Render it in Components

I want to refactor the MainMenu function and getStaticProps from index.js into separate components. Here is my current index.js page that is functioning correctly.

#index.js

import Link from 'next/link';

function MainMenu({ menuLists }) {
  return (
   <div>
      {menuLists.map(menuItem => (
        <div>
          <Link href={menuItem.absolute}><a>{menuItem.title}</a></Link>

          {menuItem.below && menuItem.below.map(childItem => (
            <div>
              <Link href={childItem.absolute}><a>{childItem.title}</a></Link>
            </div>
          ))}
        </div>
      ))}
  </div>
  )
}

export async function getStaticProps() {

  const response = await fetch('http://localhost:8888/api/menu_items/main');
  const menuLists = await response.json();
  
  return {
    props: {
      menuLists: menuLists,
    },
  }
}

export default MainMenu

I've created fetch-mainmenu.js in a lib directory with the following code.

#fetch-mainmenu.js

export async function loadMainMenu() {
    
    const response = await fetch('http://localhost:8888/api/menu_items/main')
    const menuLists = await response.json()
  
    return {
        props: {
          menuLists: menuLists,
        },
      }
  }

Then, I developed sidebar.js to display the menu system from the JSON file. The sidebar.js file is successfully showing hardcoded menus.

#sidebar.js

import Link from 'next/link'
import styles from './sidebar.module.css'
import { loadMainMenu } from '../lib/fetch-mainmenu'

export default function Sidebar({ menuLists }) {

const menus = loadMainMenu()

  return (
  
    <nav className={styles.nav}>
      <input className={styles.input} placeholder="Search..." />
      <Link href="/">
        
        <a>Home</a>
      </Link>
      <Link href="/about">
        <a>About</a>
      </Link>
      <Link href="/contact">
        <a>Contact</a>
      </Link>
    </nav>
  )
}

I'm encountering the error "TypeError: Failed to fetch". What would be the most effective approach to implementing this using components?

Answer №1

Solution

1. Prop Drilling

To easily handle data passing in React components, you can use prop drilling by sending down all the necessary data from the parent component to its children. While this method is safe, it may result in redundant props being passed around.

// Simplified code snippet for prop drilling

const MainMenuComponent = ({menuLists}) => {
  return <div>{menuLists}</div>
}

const MainPage = ({menuLists}) => {
  return <MainMenuComponent menuLists={menuLists} />
}

export async function getStaticProps() {

  const req = await fetch('...');
  
  return {
    props: {
      menuLists: req,
    },
  }
}
export default MainPage

2. Handling Asynchronous Code with useEffect

In React components, asynchronous code cannot be placed directly inside render functions as they need to be resolved asynchronously prior to rendering. This distinction between synchronous and asynchronous behavior is important for both class and functional components.

// Sample code demonstrating async handling in class and functional components

// Class Component
class SampleComponent extends React.Component {
  constructor(props) {
    super(props);
    this.state = { data: {} };
  }
  async getData() {
    const data = await fetch('...');
    this.setState({ ...this.state, data });
  }
  componentDidMount() {
    this.getData();
  }
  render() {
    // Asynchronous code cannot go here
    return <h1>Hello, {JSON.stringify(this.state.data)}</h1>;
}


// Functional Component
function SampleComponent = () => {
  // Async code outside `useEffect` does not work
  const [data, setData] = useState({});
  useEffect(async () => {
    // Proper way to handle async code within a functional component
    setData(await fetch('...'))
  }, []);

  return <h1>Hello, {JSON.stringify(data)}</h1>
}

Note: If using getStaticProps, component needs to be synchronous to avoid rehydration errors due to rapid content changes during server-side rendering. Use dynamic() wrapper if needed.

Although functional, the above methods might lead to lengthy code.

3. Leveraging TanStack Query or SWR for Data Fetching

Third-party libraries like TanStack Query and SWR offer convenient solutions for handling asynchronous data fetching within React components by providing features such as caching and revalidation mechanisms.

// Example usage of SWR library
import useSWR from 'swr'

function Profile() {
  const { data, error } = useSWR('/api/user', fetcher)

  if (error) return <div>failed to load</div>
  if (!data) return <div>loading...</div>
  return <div>hello {data.name}!</div>
}

4. State Management via Context API

For complex applications, consider implementing state management through libraries like Zustand or using plain React.Context for global data sharing. This approach helps synchronize data throughout the app but may add complexity similar to backend development.

While the Query-SWR solution is preferred for simpler cases, state management with Context API proves beneficial in specific scenarios.

// Implementing state management with Zustand + Next.js
import { useStore } from "../lib/store";
const SampleComponent = () => {
  const { data } = useStore();
  return <div>{JSON.stringify(data)}</div>
}

const MainPage() {
  return <SampleComponent />
}

export async function getStaticProps() {
  // Initialize store structure per the GitHub repo
  const zustandStore = initializeStore();

  // Update store data synchronously
  const data = await useStore.setData(await fetch('...'));

  return {
    props: {
      initialZustandState: JSON.parse(JSON.stringify({ ...zustandStore.getState(), data })),
    },
  };
}

5. Exploring Server-side Components in React 18 and Nextjs

With the advent of React 18 server-side components, there's ongoing development on integrating them into Next.js for enhanced server-side rendering capabilities. While promising, this feature is still evolving and should be closely monitored before full adoption.

Patience is key as improvements are made to stabilize the implementation of server-side components for more robust rendering processes.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Send a triggering function to two separate components

My objective is as follows: render() { return ( <div> <Child onTrigger={xxx} /> <button onClick={xxx} /> </div> ) } Upon clicking the button, I wish for some action to take place in ...

Learn the process of extracting a particular value from JSON data and displaying it in HTML by utilizing AngularJS's ng-repeat directive

As a newcomer to angularjs, I am encountering difficulties retrieving and displaying a specific value from a json file in order to showcase it on my view page using angularjs ng-repeat for image source. My goal is to repeat the json file based on a particu ...

Importing an array into DynamoDB using a JSON string with boto3

When it comes to uploading a JSON file to an AWS DynamoDB table in Python, I have been using a script that I found on this particular page. However, I am facing a challenge in understanding whether Python can be instructed to split a single string from the ...

Display a JSON encoded array using Jquery

Within an ajax call, I have a single json encoded array set: $var = json_encode($_SESSION['pictures']); The json encoded array is stored in a variable called "array" When I try to display the contents of "array" using alert, I get this respons ...

Guide to creating a menu item that redirects to a link with the use of href

I am currently working with MenuItem provided by the material-ui library. My objective is to open a link in a new tab when the menu item is clicked. The approach I have taken so far is utilizing the following code snippet: <MenuItem href="www.googl ...

How can I incorporate @twilio/flex-webchat-ui into my React Redux project?

Seeking guidance on implementing @twilio/flex-webchat-ui in my react+redux project After setting up a Twilio Flex account, I am struggling to integrate the webchat feature into my project. Despite reviewing the Twilio Flex documentation, I have not been a ...

The Journey of React Native Routing

When building my React Native application, I encountered a challenge with creating a Footer and Tab menu that should only be displayed on certain screens. If I define them within the NavigationContainer, they apply to all screens uniformly. How can I sep ...

Slow server response times in NEXTJS Amplify app

I have encountered a sluggish performance issue with my SSR App Nextjs 12 hosted on AWS Amplify. After logging the getServerSideProps() function, I discovered that the page loading time is around 9 seconds, even though the code inside getServerSideProps e ...

Within my React project, I have incorporated a popover component from Material UI. However, I have encountered an issue where the popover does not appear when hovering over the icon

I'm struggling with a certain issue. I have created a popover component that should display when the user hovers over an 'i' icon and disappear when they move away from it. However, it seems like the open and close methods are being continuo ...

Leveraging createMuiTheme to customize default styles for divs, paragraphs, and the body element

Seeking guidance on customizing a Material UI Theme I aim to modify the default styles for elements like <body>. Currently, at the root of my React tree: import theme from './mui-theme' ReactDOM.render( <Router> <ThemePr ...

How can we remove an ID from one table when the delete API is triggered in a different table?

One scenario I'm facing involves having 2 tables in my database. Let's say I delete a row (Role) from the Role Table. The question is, how can I also remove the particular role ID associated with the deleted role from the User Table? The User Ta ...

Retrieve the data stored in an array of objects

code props.thumbnails.forEach(value=>{ console.log(value.photo.thumbnail_url); }) error TypeError: Cannot read property 'thumbnail_url' of undefined Trying to loop through props.thumbnails array and access the thumbnail_url pro ...

"Exploring the source files in the NextJS directory

Recently, I began delving into NextJS. However, I'm unsure about the best practice when it comes to organizing my code. Should I follow the convention of keeping all my code (excluding the pages folder) in the /src folder like in create-react-app? Or ...

React Native: Prevent FlatList from infinitely calling onEndReached when an empty JSON array is returned from the REST API

Utilizing the infinite scrolling Flatlist design pattern in my react-native application, I have encountered an issue. After completing pagination with the REST API, it returns an empty JSON array which triggers an infinite loop in the onEndReached function ...

Extracting information from multiple JSON arrays in C#

Searching for statistics in this Json Code is my goal: { "summonerId": 32033681, "modifyDate": 1403658807000, "champions": [{ "id": 40, "stats": { "totalSessionsPlayed": 1, "totalSessionsLost": 0, ...

How can I update my outdated manifest v2 code to manifest v3 for my Google Chrome Extension?

Currently, I am developing an extension and using a template from a previous YouTube video that is based on manifest v2. However, I am implementing manifest v3 in my extension. Can anyone guide me on how to update this specific piece of code? "backgro ...

Decoding the build ID in NextJS: A step-by-step guide

When working with NextJS, there's the option to generate a build ID as mentioned in the documentation here: https://nextjs.org/docs/app/api-reference/next-config-js/generateBuildId Alternatively, it is also possible to retrieve the build ID based on ...

utilizing stateful react elements multiple times

Looking for advice as a newcomer to React. The issue I'm facing involves several component buttons that trigger a modal, where additional selection buttons are available. Home Screen Buttons (components) <Button value="First"></button> ...

What is the easiest way to include a copyright symbol in a React component?

I am trying to include the copyright symbol in a React component, but it doesn't seem to be working for me. function Footer() { return ( <footer> <p>&copy</p> </footer> ); } <p>&copy</p> ...

What is the process for setting up redux in _app.tsx?

Each time I compile my application, I encounter the following error message: /!\ You are using legacy implementation. Please update your code: use createWrapper() and wrapper.useWrappedStore(). Although my application functions correctly, I am unsure ...