This content originally appeared on flaviocopes.com and was authored by flaviocopes.com
This post is part of a new series where we build a clone of Airbnb with Next.js. See the first post here.
- Part 1: Let’s start by installing Next.js
- Part 2: Build the list of houses
- Part 3: Build the house detail view
- Part 4: CSS and navigation bar
- Part 5: Start with the date picker
- Part 6: Add the sidebar
- Part 7: Add react-day-picker
- Part 8: Add the calendar to the page
- Part 9: Configure the DayPickerInput component
- Part 10: Sync the start and end dates
- Part 11: Show the price for the chosen dates
- Part 12: Login and signup forms
- Part 13: Activate the modal
- Part 14: Send registration data to the server
- Part 15: Add postgres
- Part 16: Implement model and DB connection
- Part 17: Create a session token
- Part 18: Implement login
- Part 19: Determine if we are logged in
- Part 20: Change state after we login
- Part 21: Log in after registration
- Part 22: Create the models and move data to the db
Now that we created the model that uses the DB to serve the data, it’s time to use it!
First, I’m going to manually add the houses data we had in the file to the database, creating 2 rows in the houses table:
Now, the houses.js
file is imported by 2 files:
pages/houses/[id].js
pages/index.js
We need to change this reliance on the file, and use a new API instead.
Let’s work on the list page first.
Houses list
Instead of loading the houses from the JSON file, we’re going to use the House model.
We can use the model inside the getServerSideProps()
method. Next.js becomes an hybrid between frontend and backend.
Let’s start from pages/index.js
.
We can import the model:
import { House as HouseModel } from '../model.js'
Then in getServerSideProps()
we get the houses using:
const houses = await HouseModel.findAndCountAll()
and we return the value iterating over the results, getting the dataValues
property, which returns a plain JS object with the data we need:
return {
props: {
nextbnb_session: nextbnb_session || null,
houses: houses.rows.map((house) => house.dataValues)
}
}
Now we get houses
as a prop in the Home component:
export default function Home({ nextbnb_session, houses }) {
//...
and we need to do a little refactoring of how we print the JSX. We need to embed the content
inside the JSX, otherwise it can’t access the value of the prop, like this:
import House from '../components/House'
import Layout from '../components/Layout'
import Cookies from 'cookies'
import { useStoreActions } from 'easy-peasy'
import { useEffect } from 'react'
import { House as HouseModel } from '../model.js'
export default function Home({ nextbnb_session, houses }) {
const setLoggedIn = useStoreActions((actions) => actions.login.setLoggedIn)
useEffect(() => {
if (nextbnb_session) {
setLoggedIn(true)
}
}, [])
return (
<Layout
content={
<div>
<h2>Places to stay</h2>
<div className="houses">
{houses.map((house, index) => {
return <House key={index} {...house} />
})}
</div>
<style jsx>{`
.houses {
display: grid;
grid-template-columns: 49% 49%;
grid-template-rows: 300px 300px;
grid-gap: 2%;
}
`}</style>
</div>
}
/>
)
}
export async function getServerSideProps({ req, res, query }) {
const cookies = new Cookies(req, res)
const nextbnb_session = cookies.get('nextbnb_session')
const houses = await HouseModel.findAndCountAll()
return {
props: {
nextbnb_session: nextbnb_session || null,
houses: houses.rows.map((house) => house.dataValues)
}
}
}
The house detail
We do the same in pages/houses/[id].js
.
We import the model:
import { House as HouseModel } from '../../model.js'
Then we use it to get the house by id:
const house = await HouseModel.findByPk(id)
and we can return its dataValues
in the return object:
return {
props: {
house: house.dataValues,
nextbnb_session: nextbnb_session || null
}
}
In this case we were already returning a house
prop, so nothing needs to be changed.
Here is the full source code:
import Head from 'next/head'
import Layout from '../../components/Layout'
import DateRangePicker from '../../components/DateRangePicker'
import { useState, useEffect } from 'react'
import { useStoreActions } from 'easy-peasy'
import Cookies from 'cookies'
import { House as HouseModel } from '../../model.js'
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')
const house = await HouseModel.findByPk(id)
return {
props: {
house: house.dataValues,
nextbnb_session: nextbnb_session || null
}
}
}
You can now remove the houses.js
file, but before doing so, add the data to the database:
TIP: In the
owner
field, add the id of a user, like1
for example. This associates the house to a user in our database.
This content originally appeared on flaviocopes.com and was authored by flaviocopes.com

flaviocopes.com | Sciencx (2021-12-23T05:00:00+00:00) Airbnb clone, use the database instead of the file. Retrieved from https://www.scien.cx/2021/12/23/airbnb-clone-use-the-database-instead-of-the-file/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.