Great! Now we have the session information stored in the nextbnb_session cookie

Now I want to get the cookie value from the server on the first page load we do, and we store the login state.

Remember the store.js file we created in the previous module?

Add a new store value:

export default createStore({
  login: {
    loggedIn: false,
    setLoggedIn: action((state) => {
      state.loggedIn = true
    }),
  },
  modals: {
    //...

Now we need to add some code to pages/index.js and pages/houses/[id].js, the 2 entry points.

In pages/index.js:

//at the top
import Cookies from 'cookies'

//at the bottom
export async function getServerSideProps({ req, res, query }) {
  const cookies = new Cookies(req, res)
  const nextbnb_session = cookies.get('nextbnb_session')

  return {
    props: {
      nextbnb_session: nextbnb_session || null,
    },
  }
}

This makes the nextbnb_session prop available in the component.

We use useEffect now to check if this prop is available, and if so, we are going to call the setLoggedIn state action:

//at the top
import { useStoreActions } from 'easy-peasy'
import { useEffect } from 'react'

//...
export default function Home({ nextbnb_session }) {
  const setLoggedIn = useStoreActions((actions) => actions.login.setLoggedIn)

  useEffect(() => {
    if (nextbnb_session) {
      setLoggedIn(true)
    }
  }, [])

  //...

We do the same in pages/houses/[id].js. Here is the full code of the component:

import Head from 'next/head'
import houses from '../../houses.js'
import Layout from '../../components/Layout'
import DateRangePicker from '../../components/DateRangePicker'
import { useState, useEffect } from 'react'
import { useStoreActions } from 'easy-peasy'
import Cookies from 'cookies'

const calcNumberOfNightsBetweenDates = (startDate, endDate) => {
  const start = new Date(startDate) //clone
  const end = new Date(endDate) //clone
  let dayCount = 0

  while (end > start) {
    dayCount++
    start.setDate(start.getDate() + 1)
  }

  return dayCount
}

export default function House({ house, nextbnb_session }) {
  const [dateChosen, setDateChosen] = useState(false)
  const [numberOfNightsBetweenDates, setNumberOfNightsBetweenDates] = useState(
    0
  )

  const setShowLoginModal = useStoreActions(
    (actions) => actions.modals.setShowLoginModal
  )

  const setLoggedIn = useStoreActions((actions) => actions.login.setLoggedIn)

  useEffect(() => {
    if (nextbnb_session) {
      setLoggedIn(true)
    }
  }, [])

  return (
    <Layout
      content={
        <div className='container'>
          <Head>
            <title>{house.title}</title>
          </Head>
          <article>
            <img src={house.picture} width='100%' alt='House picture' />
            <p>
              {house.type} - {house.town}
            </p>
            <p>{house.title}</p>
          </article>
          <aside>
            <h2>Choose a date</h2>
            <DateRangePicker
              datesChanged={(startDate, endDate) => {
                setNumberOfNightsBetweenDates(
                  calcNumberOfNightsBetweenDates(startDate, endDate)
                )
                setDateChosen(true)
              }}
            />

            {dateChosen && (
              <div>
                <h2>Price per night</h2>
                <p>${house.price}</p>
                <h2>Total price for booking</h2>
                <p>${(numberOfNightsBetweenDates * house.price).toFixed(2)}</p>
                <button
                  className='reserve'
                  onClick={() => {
                    setShowLoginModal()
                  }}
                >
                  Reserve
                </button>{' '}
              </div>
            )}
          </aside>

          <style jsx>{`
            .container {
              display: grid;
              grid-template-columns: 60% 40%;
              grid-gap: 30px;
            }

            aside {
              border: 1px solid #ccc;
              padding: 20px;
            }
          `}</style>
        </div>
      }
    />
  )
}

export async function getServerSideProps({ req, res, query }) {
  const { id } = query
  const cookies = new Cookies(req, res)
  const nextbnb_session = cookies.get('nextbnb_session')

  return {
    props: {
      house: houses.filter((house) => house.id === parseInt(id))[0],
      nextbnb_session: nextbnb_session || null,
    },
  }
}

Now we need to change components/Header.js to show a “Logged in” state in the header instead of the links to login and signup.

We first import

import { useStoreState, useStoreActions } from 'easy-peasy'

and inside the component we define

const loggedIn = useStoreState((state) => state.login.loggedIn)
const setLoggedIn = useStoreActions((actions) => actions.login.setLoggedIn)

Finally we add this JSX:

{
  loggedIn ? (
    <nav>
      <ul>
        <li>
          <a>Logged in</a>
        </li>
      </ul>
    </nav>
  ) : (
    <nav>
      <ul>
        <li>
          <a href='#' onClick={() => setShowRegistrationModal()}>
            Sign up
          </a>
        </li>
        <li>
          <a href='#' onClick={() => setShowLoginModal()}>
            Log in
          </a>
        </li>
      </ul>
    </nav>
  )
}

The code for this lesson is available at https://github.com/flaviocopes/airbnb-clone-react-nextjs-2020/tree/5-5


Go to the next lesson