Why the data not displayed in nextjs?

2020-03-26 06:31发布

问题:

I am making a very very simple nextjs application where I am trying to fetch the data from api.

My requirement is I should display the data in layout.js file and this layout.js file is a children in index.js file.

index.js:

import Layout from "./layout";
import React from "react";

class Home extends React.Component {
  render() {
    return (
      <div>
        <Layout />
        <h4> Main content will be displayed here !! </h4>
      </div>
    );
  }
}

export default Home;

layout.js:

import React from "react";
import fetch from "isomorphic-unfetch";

function Layout(props) {
  return (
    <div>
      <p>Preact has {props.stars} ⭐</p>
      <p> Why I couldn't get the above "props.star" ? </p>
    </div>
  );
}

Layout.getInitialProps = async () => {
  console.log("comes into layout getinitial props");
  const res = await fetch("https://api.github.com/repos/developit/preact");
  const json = await res.json(); // better use it inside try .. catch
  return { stars: json.stargazers_count };
};

export default Layout;

So as per the above given code, I have called the layout page inside index.js page (in my real application I need to call like this only so no changes in calling layout inside index)..

But when I made a console.log() in the function Layout.getInitialProps in layout, it doesn't print anything and hence the api data not fetched..

Complete working demo here with code

Why can't I fetch the data inside the layout.js while calling as a children from index.js?

Also provide me the right updated solution to achieve this.. I really searched for many questions but none solved my issue and I couldn't understand those solutions clearly so please help me with the above given example.

回答1:

That because getInitialProps can only be added to the default component exported by a page, adding it to any other component won't work.
You should use componentDidMount() or useEffect instead, or move getInitialProps in the index and then pass the result to the component. something like (not tested) :

index.js :

import Layout from "./layout";
import React from "react";

class Home extends React.Component {
  render() {
    return (
      <div>
        <Layout />
        <h4> Main content will be displayed here !! </h4>
      </div>
    );
  }
}

export default Home;

layout.js

import React from "react";
import fetch from "isomorphic-unfetch";
class Layout extends React.Component {
  constructor(props) {
    super(props);
    this.state = {
      stars: false
    };
  }
  async componentDidMount() {
    console.log("comes into layout getinitial props");
    const res = await fetch("https://api.github.com/repos/developit/preact");
    const json = await res.json(); // better use it inside try .. catch
    this.setState({ stars: json.stargazers_count });
  }
  render() {
    const { stars } = this.state;
    return (
      <div>
        <p>Preact has {stars} ⭐</p>
        <p> Why I couldn't get the above "props.star" ? </p>
      </div>
    );
  }
}

export default Layout;

Edit: Example with class component
Bonus: If you want to add the layout for all the pages of your app this isn't the best approach, instead you should take a look to custom _app.js, example