Home > front end >  nextjs getStaticProps not working in my component
nextjs getStaticProps not working in my component

Time:05-21

I have the following component which I then import and use in a page. Unfortunately I am getting the error error - TypeError: Cannot read property 'labels' of undefined and data and options are underlined in the line where I pass them to ChartCard. I tried to follow the docs as close as I can but I guess I must be doing something wrong.

import faker from '@faker-js/faker'
import {
  CategoryScale,
  Chart as ChartJS,
  Legend,
  LinearScale,
  LineElement,
  PointElement,
  Title,
  Tooltip,
} from 'chart.js'
import { Line } from 'react-chartjs-2'
import BaseCard from './BaseCard'

ChartJS.register(
  CategoryScale,
  LinearScale,
  PointElement,
  LineElement,
  Title,
  Tooltip,
  Legend
)
export async function getStaticProps() {
  const options = {
    responsive: true,
    plugins: {
      legend: {
        position: 'top' as const,
      },
      title: {
        display: true,
        text: 'Price',
      },
    },
  }
  const labels = [
    'January',
    'February',
    'March',
    'April',
    'May',
    'June',
    'July',
  ]
  const data = {
    labels,
    datasets: [
      {
        label: 'Dataset 1',
        data: labels.map(() => faker.datatype.number({ min: 2000, max: 4000 })),
        borderColor: 'rgb(255, 99, 132)',
        backgroundColor: 'rgba(255, 99, 132, 0.5)',
      },
    ],
  }

  return {
    props: { options, data },
  }
}


export default function ChartCard({ options, data }) {
  return (
    <BaseCard>
      <Line options={options} data={data} />
    </BaseCard>
  )
}

Edit: I've now refactored my code to have the getStaticProps in the index.js page as follows:

#index.tsx
import type { NextPage } from 'next'
import faker from '@faker-js/faker'
import ChartCard from '../components/ChartCard'

export async function getStaticProps() {
  const options = {
    responsive: true,
    plugins: {
      legend: {
        position: 'top' as const,
      },
      title: {
        display: true,
        text: 'IndexCoin Price',
      },
    },
  }
  const labels = [
    'January',
    'February',
    'March',
    'April',
    'May',
    'June',
    'July',
  ]
  const data = {
    labels,
    datasets: [
      {
        label: 'Dataset 1',
        data: labels.map(() => faker.datatype.number({ min: 2000, max: 4000 })),
        borderColor: 'rgb(255, 99, 132)',
        backgroundColor: 'rgba(255, 99, 132, 0.5)',
      },
    ],
  }

  return {
    props: { options, data },
  }
}

const Home: NextPage = (options, data) => {
  console.log(options)
  console.log(data)
  console.log(data.datasets)
  return(
    <ChartCard options={options} data={data} />
  )
}

The console output of this is:

options: { responsive: true, plugins: { legend: [Object], title: [Object] } },
  data: {
    labels: [
      'January', 'February',
      'March',   'April',
      'May',     'June',
      'July'
    ],
    datasets: [ [Object] ]
  }
}
{}
undefined

And this crashes because datasets is undefined. Why is this happening?

CodePudding user response:

You can only use getStaticProps in a NextJS page (i.e. component under src/pages/MyPageComponent.js).

(https://nextjs.org/docs/basic-features/data-fetching/get-static-props)

This means that your ChartCard is being called with options=undefined and data=undefined as the getStaticProps never runs.

It certainly would be nice to be able to encapsulate the server-side data fetching and rendering in one component file, but unfortunately this isn't possible right now.

What you'll need to do is to add an api to e.g. src/api/MyApi.js and call that in your component.

E.g. a quick example to start from:

src/api/MyApi.js

export default function MyApi(req, res) {
  //... do your data fetching
  res.send({options, data})
}

src/components/MyComponent.js

const [result, setResult] = useState();
useEffect(async ()=>{
  const res = await fetch('/api/MyApi');
  const result = await res.json();
  setResult(result);
}, []);

const {options, data} = result ?? {};

Note the above will perform client-side data fetching so will need a live server.

If you're expecting to build static pages at build time then your only option (IIRC) is to capture ALL the data needed in the src/pages/MyPage.js's getStaticProps and pass them into the page's components as needed.

CodePudding user response:

if this code is exact copy of your project there is a typo in it:

position: 'top' as const

try this:

position: 'top as const'

and also use getStaticProps for page components

  • Related