Невозможно передать реквизит в следующем - PullRequest
3 голосов
/ 09 апреля 2020

Я делаю приложение для рендеринга на стороне сервера, используя Next Js (React SSR).

Index. js (просто вызывая компоновку другого компонента в индексе)

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

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

export default Home;

Компоновка. js

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

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

  componentDidMount() {
    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.com/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.com/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;

Полный простой пример применения приведен здесь : https://codesandbox.io/s/nextjs-getinitialprops-748d5

Моя проблема здесь в том, что я пытаюсь передать реквизиты на страницу product со страницы layout, а реквизиты принимаются от getInitialProps (SSR). Но вы можете увидеть в В приведенном примере реквизит не работает, и он по-прежнему выдает undefined для this.props.stars.

Если переместить этот код в componentDidMount и использовать setState и передать состояние в качестве реквизита будет работать, но это не будет отображать данные, извлеченные из API в исходной странице просмотра.

Примечание: Пожалуйста, не перемещайте этот лог c в индексный файл. js файл, где он работает, но в моем реальном приложении это динамическая c страница маршрутизации, и я получу API в соответствии с параметром запроса, полученным на этой странице.

Если вы получите по этой ссылке https://748d5.sse.codesandbox.io/ и нажмите ctrl + u, тогда вы увидите источник, где я также нуждаюсь в динамическом c содержимом, полученном из API.

Для достижения этой динамически c содержимое (количество звездочек здесь в этом примере) отображается только в виде источника. Я делаю все это, что предназначено для целей SEO.

1 Ответ

2 голосов
/ 09 апреля 2020

Короче говоря, вы не можете вызвать getInitialProps из дочернего компонента: getInitialProps caveats .

getInitialProps нельзя использовать в дочерних компонентах , только при экспорте каждой страницы по умолчанию

Ваша Layout страница является дочерним компонентом из Home.

Если вы хотите вызвать getInitialProps, то вам нужно либо определить getInitialProps на странице Home, либо создать компонент-обертку, который вызывает свой собственный getInitialProps это обернет default export PageComponet страницы следующим компонентом-оберткой: export default withStarsData(PageComponent); в результате этот компонент-оболочка затем будет передавать PageComponent some props.

Если вы хотите сделать эту функцию гибкой / dynamici c, тогда используйте ctx 's * Параметр 1028 * с Dynami c Маршрут .

Это довольно сложное решение для понимания, но вкратце, оно позволяет дома (/) и макет (* 1034) *) страницы для извлечения одинаковых данных. Если вы не хотите извлекать данные несколько раз, а вместо этого извлекаете ОДИН РАЗ, а затем делитесь между страницами, вам следует использовать провайдера состояний более высокого порядка, например redux .

Рабочий пример :

Edit GetInitialProps Wrapper


компонентов / 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.com/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;
...