最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Unable to pass props in Next - Stack Overflow

programmeradmin3浏览0评论

I am making a Server Side Rendering application using Next Js (React SSR).

Index.js (Simply calling another ponent Layout in index)

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

class Home extends React.Component {
  render() {
    return (
      <div>
        <Layout />
      </div>
    );
  }
}

export default Home;

Layout.js

import React from "react";
import Product from "./product";

class Layout extends React.Component {
  static async getInitialProps() {
    const res = await fetch("");
    console.log(res);
    const json = await res.json();
    return { stars: json.stargazers_count };
  }

  ponentDidMount() {
    if (localStorage.getItem("userLoggedIn")) {
      //Get products details for logged in user api
      //For now let us consider the same api
      // const res = fetch("");
      // const json = res.json(); // better use it inside try .. catch
      // return { stars: json.stargazers_count };
    } else {
      // Get product details for guest user api
      //For now let us consider the same api
      // const res = fetch("");
      // const json = res.json(); 
      // return { stars: json.stargazers_count };
    }
  }

  render() {
    return (
      <div>
        This is layout page
        <Product stars={this.props.stars} />
      </div>
    );
  }
}

export default Layout;

Complete simple application example is here:

My problem here is, I am trying to pass props to product page from layout page and props are received from getInitialProps (SSR).. But you could see in the example provided, the props didn't works and it still gives undefined for this.props.stars .

If I move this code into ponentDidMount and using setState and passing state as props would work but that will not display the data fetched from api in view page source.

Note: Please don't move this logic into index.js file where it works but in my real application It is dynamic routing page and I will fetch api as per the query param fetched on that page.

If you get into this link / and click ctrl + u then you would see the source where I am also need the dynamic content fetched from api.

To achieve this dynamic content(stars count here in this example) display in view source only I am doing all these which is meant for SEO purpose.

I am making a Server Side Rendering application using Next Js (React SSR).

Index.js (Simply calling another ponent Layout in index)

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

class Home extends React.Component {
  render() {
    return (
      <div>
        <Layout />
      </div>
    );
  }
}

export default Home;

Layout.js

import React from "react";
import Product from "./product";

class Layout extends React.Component {
  static async getInitialProps() {
    const res = await fetch("https://api.github./repos/developit/preact");
    console.log(res);
    const json = await res.json();
    return { stars: json.stargazers_count };
  }

  ponentDidMount() {
    if (localStorage.getItem("userLoggedIn")) {
      //Get products details for logged in user api
      //For now let us consider the same api
      // const res = fetch("https://api.github./repos/developit/preact");
      // const json = res.json(); // better use it inside try .. catch
      // return { stars: json.stargazers_count };
    } else {
      // Get product details for guest user api
      //For now let us consider the same api
      // const res = fetch("https://api.github./repos/developit/preact");
      // const json = res.json(); 
      // return { stars: json.stargazers_count };
    }
  }

  render() {
    return (
      <div>
        This is layout page
        <Product stars={this.props.stars} />
      </div>
    );
  }
}

export default Layout;

Complete simple application example is here: https://codesandbox.io/s/nextjs-getinitialprops-748d5

My problem here is, I am trying to pass props to product page from layout page and props are received from getInitialProps (SSR).. But you could see in the example provided, the props didn't works and it still gives undefined for this.props.stars .

If I move this code into ponentDidMount and using setState and passing state as props would work but that will not display the data fetched from api in view page source.

Note: Please don't move this logic into index.js file where it works but in my real application It is dynamic routing page and I will fetch api as per the query param fetched on that page.

If you get into this link https://748d5.sse.codesandbox.io/ and click ctrl + u then you would see the source where I am also need the dynamic content fetched from api.

To achieve this dynamic content(stars count here in this example) display in view source only I am doing all these which is meant for SEO purpose.

Share Improve this question edited Apr 9, 2020 at 0:09 asked Apr 9, 2020 at 0:03 user12856847user12856847
Add a ment  | 

1 Answer 1

Reset to default 6

In short, you can't call getInitialProps from a child ponent: getInitialProps caveats.

getInitialProps can not be used in children ponents, only in the default export of every page

Your Layout page is a child ponent of Home.

If you want to call getInitialProps, then you'll either need to define getInitialProps from within the Home page OR create a wrapper ponent that calls its own getInitialProps that will wrap the page's default export PageComponet with this wrapper ponent: export default withStarsData(PageComponent); as a result, this wrapper ponent will then pass PageComponent some props.

If you want to make this function flexible/dynamic, then use ctx's query parameter with a dynamic route.

This is a rather plex solution to understand, but in brief, it allows the home (/) and layout (/layout) pages to fetch the same data. If you don't want to fetch the data multiple times, but instead, fetch ONCE and then share between pages, then you'll want to use a higher-order state provider like redux.

Working example:


ponents/withStars/index.js

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

// 1.) this function accepts a page Component and...
const withStars = WrappedComponent => {

  // 7.) if stars data is present, returns <WrappedComponent {...props} /> with props
  // else if there's an error, returns the error
  // else returns a "Loading..." indicator
  const FetchStarsData = props =>
    props.stars ? (
      <WrappedComponent {...props} />
    ) : props.error ? (
      <div>Fetch error: {props.error} </div>
    ) : (
      <div>Loading...</div>
    );

  // 3.) this first calls the above function's getInitialProps
  FetchStarsData.getInitialProps = async ctx => {

    // 4.) here's where we fetch "stars" data
    let stars;
    let error;
    try {
      const res = await fetch("https://api.github./repos/developit/preact");
      const json = await res.json();
      stars = json.stargazers_count;
    } catch (e) {
      error = e.toString();
    }

    // 5.) optionally this will call the <WrappedComponent/> 
    // getInitialProps if it has been defined
    if (WrappedComponent.getInitialProps)
      await WrappedComponent.getInitialProps(ctx);

    // 6.) this returns stars/error data to the FetchStarsData function above
    return { stars, error };
  };

  // 2.) ...returns the result of the "FetchStarsData" function
  return FetchStarsData;
};

export default withStars;
发布评论

评论列表(0)

  1. 暂无评论