3

I am using Next.js, in the _app.js page (where we set a general webapp state) I have 2 types of data that I need to have in the header (so for every component).

1) The first type is the header info, this info should be rendered before the app loads. I will use get getInitialProps to call the endpoints and put them into the props and then to componentWillMount to add them to the state.

2) The second type is the data for the Search component, it as a lot of data and I don't particularly mind loading it while the app is already rendered as It is not displayed in the first user visual. So I am gussing that here it is much better prefered to use componentDidMount and asynchorslly call the endpoint that fetches the serach object data and than adding setting the state with it.

The purpose of this questionis double:

1) Review - Am I thinking about this correctly or did I miss something?

2) Question - now, when the data is loaded after first render, I am passing the data like so: _app.js -> Layout -> Menu -> SearchBar so my question is, in my searchBar I need to do something like

componentDidMount() {
    this.setState({ options: this.props.searchBarSource })
}

But, because _app.js is filling this data with an async call, wouldn't this mean that I will always get an empty object? WWhat is the correct way to solve this? If I setTimeOut to around 3 seconds and then set the data is it a normal solution or very hacky and there are better ways?

Contentop
  • 1,163
  • 3
  • 20
  • 43
  • 1
    you can use life-cycles to detect changes in `this.props.searchBarSource` and store accordingly. But do you really need to synchronize props to state? Can't you use `this.props.searchBarSource` where you normally would use `this.state.options`? – Kunukn Jan 03 '19 at 13:58

1 Answers1

1

What your are trying to do makes sense. Coming to NextJS, you need to be very deliberate about which data should load server side and which shouldn't.

Here are some pointers:

  1. There is no need to setState in the search component, you can use this.props.searchBarSource as Kunukn mentioned.

    [Note - If you are combining getInitialProps and client side (shallow routing), when the user navigates to a new client side route, the initialProps will be undefined. A workaround might be to store initialProps in state or Local Storage.]

  2. The point of getInitialProps is to load async data before the component mounts. You will always receive the resolved Promise on componentDidMount, so your this.props.searchBarSource will never be empty (or more correctly, pending).

Avi Kaminetzky
  • 1,489
  • 2
  • 19
  • 42
  • 1
    Yeah you were right about passing the searchBar as a props, not state, after doing so and putting it in the componentDidMount function it works great. So what is better? using getInititialProps for props that appear to the user all the time and use componentDidMount when you want to fetch data that the user doesn'r see first? Or just fetch everything in getInitialProps without the componentDidMount part? – Contentop Jan 04 '19 at 01:05
  • 1
    The former. For example, I have a product page which needs to be rendered server side for optimal user experience and SEO. But I only need the main data to be available in order to render the page (price, image, basic shipping). That would go in `getInitialProps`. But secondary widgets, especially if they are below the fold, can have their data fetched on component mount. – Avi Kaminetzky Jan 04 '19 at 01:43
  • 1
    At the end of the day you are making a tradeoff: Do you want the page to do more server side fetches and no loading spinners? Have everything fetched in `getInitialProps`. If you are fine with loading spinners for some things, fetch client side. – Avi Kaminetzky Jan 04 '19 at 01:47