ReactJS & GraphQL Full Stack Real Estate Web App (2024)

Luke Ostrander

·

Follow

12 min read

·

Apr 11, 2022

--

ReactJS & GraphQL Full Stack Real Estate Web App (3)

Background

After completing part 1 of my real estate website, I realized there were many things I wanted to change on the existing site. While I really liked some features, such as the Hero image and navbar, I noticed that the way I was building the website wouldn’t be able to scale well. This is because with the design I was building, each page was going to have a single house, and involve a great deal of scrolling up and down just to view the houses one by one. I decided that I wanted to scrap most of what I did before for this reason, but carry forward the features of the site that I really liked.

My main strategy in building the complete website was to go back to the start, and change the parts of the site as I went along and add new features in.

Project: Front-End

From completing part 1 of my project, I found the React state hook to be a confusing concept. I wanted to determine its purpose, and how I might be able to use it more effectively in other areas of the site. According to the React documentation, the most notable advantage of hooks is that they allow you to use state. This refers to plain JavaScript objects used by React for representing the information of a component’s current situation, which is managed by the component itself. In addition to this, hooks can be used instead of writing classes. Inside a function component, we are unable to use this.state. Instead, we can call useState directly in the component, which provides the exact same capabilities as this.state does in a class. Calling useState declares a state variable. Below is an example I found from the React documentation.

// Using classes
class Example extends React.Component {
constructor(props) {
super(props);
this.state = {
count: 0
};
}
render() {
return (
<div>
<p>You clicked {this.state.count} times</p>
<button onClick={() => this.setState({ count: this.state.count + 1 })}>
Click me
</button>
</div>
);
}
}
//Using state hook
import React, { useState } from 'react';
function Example() {
// Declare a new state variable, which we'll call "count"
const [count, setCount] = useState(0);
return (
<div>
<p>You clicked {count} times</p>
<button onClick={() => setCount(count + 1)}>
Click me
</button>
</div>
);
}

In this example, I wanted to specify the initial state for the count, and increment this by one each time. When useState is returned, it holds the current state of the component, count and the setCount function that updates it.

My biggest obstacle when creating the front end was that I kept having issues using relative file paths. For some reason, this didn’t give me much of an issue for part 1 of this project. However, there were so many more files and directories it got very confusing to do imports. I kept having to modify the relative paths if I wanted to reorganize my file structures. Apparently, this was a very common issue that many other people who worked with React faced. I discovered that if I wanted to use absolute paths, which I have the most familiarity with, I needed to create a jsconfig.json file in the root directory.

{
"compilerOptions": {
"baseUrl": "src"
}
}

This means that in addition to being able to import using relative paths, I can now import files with the absolute path starting at the src directory. Below is an example of when I wanted to import an image file into my Section1.js file. As you can see, it can definitely get more challenging managing your files as the size of a project gets bigger.

//Old method using relative path from root directory
import building6 from "../../../../assets/building6.jpg";
//New method using src as the absolute path
import building6 from "assets/building6.jpg";

Another type of React syntax that I was confused by were events. These are actions that React can perform based on what the user does. Below is an example:

// Creates input box 
<input
type="text"
placeholder="Enter a Location"
onChange={(e) => setLocation(e.target.value)} // Event line
/>

The e.target represents the element that triggers the event. In this case, the user would input a string value for a location that is currently set to the placeholder, and e.target.value gets the value of the element, and updates the event to that.

After creating part 1 of my real estate website, I realized that I wanted to redesign most of what I created. The only two aspects I kept the same were the navbar and Hero image sliders. For the next section of the site after these, I decided it would be good to add the search functionality to the site. I experimented with having a picture behind the text. I knew that in order for it to be easily readable, I would somehow need to fade out the image. To do this, rather than changing the style of the image directly, I just changed the background color of the slogan itself.

Search Menu

ReactJS & GraphQL Full Stack Real Estate Web App (4)

Remembering what I learned from last time, I decided to create a button that would be reused across different areas of the web app. In order to do this, I found a more clever way to add data into a button. In addition to this, I created default specifications for the button that made testing the implementation much easier.

import { Link } from "react-router-dom";
import { BsArrowRight } from "react-icons/bs";
import styles from "./Buttons.module.scss"
const ArrowButton = ({ text, path }) => {
return(
<div className={styles.btn}>
<Link to={`${path}`}>{text}</Link>
<BsArrowRight />
</div>);
};
ArrowButton.defaultProps = {
text: "Test",
path: "/",
};

export { ArrowButton };

For the next section of the web app, I decided to add ways in which the specific property types could be accessed. Aside from being able to use the dropdown and navbar, I thought it would be very helpful for the user of the web app to understand where to go to access certain types of properties. The button I used here was the one I previously showed how to create above. Due to the improved method of creating the button, adding this into JavaScript files is far easier.

{/* BUY HOMES SECTION */}
<div className={styles.buy}>
<h3>Buy a home</h3>
<p>
Find the most beautiful homes, all of which feature
an immersive photographic experience. You'll see
properties that are impossible to find anywhere else.
</p>
<ArrowButton text={"Search Houses"} path="buy" />
</div>

Find by property type

ReactJS & GraphQL Full Stack Real Estate Web App (5)

For the next section of the web app, I wanted to add featured homes that the user could swipe through. This functionality is referred to as a carousel, which is utilized to display many images in a single space. This improves visual appeal, by encouraging users to focus on the most important aspects of the web app. For the carousel I decided to use Swiper, which is a modern touch slider intended to be used when viewing the web app from a mobile device. In the Carousel component, slides contain the properties of each of the children, which are the individual slide components of the carousel. Aside from swiping through, Pagination enables the user to click through to different pictures.

const Carousel = ({ children, slides }) => {
return (
<Swiper
modules={[Pagination]}
spaceBetween={50}
sliderPerView={slides}
pagination={{ clickable: true }}
>
{children}
{/* PAGINATION MARGIN */}
<div style={{ marginTop: "70px" }}></div>
</Swiper>
);
};
Carousel.defaultProps = {
slides: "auto",
};

Next I created the card component, which represents the elements inside the carousel that can be swiped through. Until the back end is developed, every card component will have the same default image and metadata, which I passed in using JSON.

//default Props
Card.defaultProps = {
info: {
id: undefined,
imageSource: placeholder,
category: "Buy",
city: "Default City",
neighborhood: "Default Neighborhood",
street: "Default Street",
rooms: 6,
bedrooms: 3,
bathrooms: 2,
shortAddress: "Default",
price: 325000,
rent: 0,
},
showInfo: {
price: true,
rent: false,
},
secondClass: "undefined",
};

Carousel with card components

ReactJS & GraphQL Full Stack Real Estate Web App (6)

I found implementing the next two sections about the track record of the business and where to get started, pretty straightforward after figuring out the previous parts of the web app. My favorite aspect of creating these was having two pictures staggered behind the text, which I thought looked very cool, and was actually pretty simple to create.

.image_container_1 {
position: relative;
z-index: -2;
margin-right: 1.5rem;
display: flex;
align-items: flex-end;
img {
width: 500px;
height: 450px;
object-fit: cover;
@media screen and (max-width: 1100px) {
width: 400px;
}
}
}
.image_container_2 {
position: relative;
display: flex;
align-items: flex-end;
z-index: -2;
img {
width: 40vw;
height: 500px;
object-fit: cover;
}
}

Having the pictures set to flex-end aligns them at the bottom, so then when I make the heights different and set a margin, these are the results:

ReactJS & GraphQL Full Stack Real Estate Web App (7)

When creating the footer about the company information, I used React Icons. There is a subdirectory in here called AI that has icons for various companies, so I used these to represent the social media platforms where UPST8 Empire has a presence.

The front end is now complete! In order to create the search, buy, and rent pages, I will be using GraphQL through fetching data from the back end.

ReactJS & GraphQL Full Stack Real Estate Web App (8)

Project: Back-End

While I have used REST for creating my Java Spring and PostGres API project, I wanted to try something different. Recently I have heard of GraphQL, which is an open source data query and manipulation language that has been gaining traction as a potential replacement to REST APIs. After researching, I discovered that this isn’t true for all cases, but substituting GraphQL APIs for REST APIs can be advantageous in certain circ*mstances. There are multiple ways that GraphQL stands out:

  • Clients can fetch the exact resources needed from the server
  • Automatic validation and type checking
  • Faster performance and development speeds
  • Easily aggregate data from various sources

If you would like to learn more about GraphQL, I’d suggest watching this short explanation video first.

In order to create the back end using GraphQL, I decided to use Strapi. According to this article:

Strapi is an open-source headless CMS used for building fast and easily manageable APIs written in JavaScript. It enables developers to make flexible API structures easily using a beautiful user interface.

Strapi can be used with various databases including MongoDB, PostgreSQL, etc.

A CMS refers to a content management system, which is a type of software used to create, edit, and manage a website. When it comes to ones that are headless, this means that instead of having your content linked to a web page, it provides the content as data through an API. The value in this type of CMS is that you can choose the heads (outputs) that the content is sent to. While I have never used something like this before, I thought it would be interesting to try for this project.

Next I ran the installation script, which is npx create-strapi-app@latest Back-End --quickstart, with the Back-End being the name of my project. After creating a Strapi account, I can start building the data architecture for the content of my web app.

ReactJS & GraphQL Full Stack Real Estate Web App (9)

Along with this, I needed to navigate to the Back-End folder I just created to install GraphQL using npm run strapi install graphql. Now I have everything I need to start development and can run npm run develop.

In Strapi, I created collection types for house, location, category, and user. In hardly no time at all, I have begun to really enjoy using Strapi due to how simple yet appealing the UX/UI is. Below are some examples of creating collection types:

ReactJS & GraphQL Full Stack Real Estate Web App (10)
ReactJS & GraphQL Full Stack Real Estate Web App (11)

After adding these in and saving, the necessary http requests are automatically generated, which updates the back end. Now, I am able to make entries from each of the collections I previously created.

ReactJS & GraphQL Full Stack Real Estate Web App (12)

Once some entries are created, I can run queries to access the specific information I desire. This is done through typing localhost:1337/graphql into the web browser after modifying the permissions in Strapi.

Querying Test Entry

ReactJS & GraphQL Full Stack Real Estate Web App (13)

In order to get the entries from Strapi to appear in the web app, I need to use Apollo. This is a caching GraphQL client that is able to integrate with React among other frameworks. Through building UI components with Apollo, I can then fetch, cache, and modify data through GraphQL. What makes Apollo amazing is that it automatically updates the UI of my web app as I use it. To install, I entered the command npm i graphql @apollo/client after navigating to the front end directory. After this, I created the Apollo client in my App.js file.

import "./App.scss";
import { Routes, Route } from "react-router-dom";
import Home from "./components/Pages/Home/Home";
import { ApolloClient, InMemoryCache, ApolloProvider } from "@apollo/client";
const client = new ApolloClient({
uri : "http://localhost1337/graphql:",
cache: new InMemoryCache(),
})
function App() {
return (
<ApolloProvider client={client}>
<div className="App">
<Routes>
<Route path="/" element={<Home />} />
</Routes>
</div>
</ApolloProvider>
);
}
export default App;

Following this, I wanted to run a query using GraphQL and Apollo to update the featured homes section. Previously, I used the same card that I labeled as default in order to test if the carousel was working properly. When adding this query into React, I kept getting the “400: Bad request” error. After spending a long time on this, I realized that I had misspelled a few words. The quick fix to check this is to simply copy and paste the query from React into the local GraphQL environment and you will immediately know if something is off.

GraphQL Query Implemented in React

const CARD_DATA = gql` query GET_CARDS {
houses(
filters: { categories: { Category: { contains: "Buy" } } }
pagination: { limit: 6 }
) {
data {
id
attributes {
location {
data {
attributes {
City
}
}
}
Preview_Image {
data {
attributes {
url
}
}
}
categories {
data {
attributes {
Category
}
}
}
Neighborhood
Street
Rooms
Bedrooms
Bathrooms
Short_Address
Price
}
}
}
}
`;

Updated UI

ReactJS & GraphQL Full Stack Real Estate Web App (14)

Following this, I created the buy, rent, and error 404 page. In order to do this, I added extra route paths into the App.js file. Along with this, I created JavaScript files for the buy and rent pages. These utilized GraphQL queries that are very similar to the one above which limited the number of cards with buy to 6. In this case, I returned all houses, with buy and rent appearing on their respective pages.

ReactJS & GraphQL Full Stack Real Estate Web App (15)

The last thing I wanted to create was dynamic routing for the homes on each page. To do this, I added an additional route path called property. In this file, it would query by filtering the house id, so that when a specific home is clicked on, only that information about it would be returned as a card.

Dynamic Routing

ReactJS & GraphQL Full Stack Real Estate Web App (16)

Deployment

In order to deploy the web app, I decided to use Netlify. While I was trying to deploy the front and back ends of the app together, I only managed to be able to do the front end, which meant that none of the houses were able to show up when using it through the web server. In the next app I build, my main objective will be to learn how to do this, and be able to make changes to the app in real time.

TLDR Version

After creating a UI in React, I was originally planning on just developing a front end project. However, I realized that this would be the perfect opportunity to take what I have learned from part 1, improve the front end, as well as develop a back end using technologies that were new to me. Overall, this was an amazing learning experience and I really look forward to seeing what types of apps I’ll be able to build in the future.

Works Cited

Fireship. GraphQL Explained in 100 Seconds. YouTube, YouTube, 13 Feb. 2021, https://www.youtube.com/watch?v=eIQh02xuVw4&t=82s. Accessed 10 Apr. 2022.

Ganatra, Ronak. “GraphQL vs. Rest APIs.” GraphCMS, GraphCMS, 11 Nov. 2021, https://graphcms.com/blog/graphql-vs-rest-apis#what-is-a-rest-api.

Mastery, JavaScript, director. The Best Way to Host & Deploy a React Application. YouTube, YouTube, 22 Oct. 2020, https://www.youtube.com/watch?v=Ey_90l9GaAw&t=315s. Accessed 10 Apr. 2022.

Melvær, Knut. “Headless CMS Explained In 1 Minute.” Sanity.io, Sanity, 25 Jan. 2022, https://www.sanity.io/blog/headless-cms-explained.

Mungai, Geoffrey. “Getting Started with Strapi API CMS.” Section, Section, https://www.section.io/engineering-education/getting-started-with-strapi/#:~:text=Strapi%20is%20an%20open%2Dsource,including%20MongoDB%2C%20PostgreSQL%2C%20etc.

“Using the State Hook.” React, Meta Platforms, Inc., https://reactjs.org/docs/hooks-state.html.

ReactJS & GraphQL Full Stack Real Estate Web App (2024)
Top Articles
Latest Posts
Article information

Author: Fr. Dewey Fisher

Last Updated:

Views: 6498

Rating: 4.1 / 5 (42 voted)

Reviews: 81% of readers found this page helpful

Author information

Name: Fr. Dewey Fisher

Birthday: 1993-03-26

Address: 917 Hyun Views, Rogahnmouth, KY 91013-8827

Phone: +5938540192553

Job: Administration Developer

Hobby: Embroidery, Horseback riding, Juggling, Urban exploration, Skiing, Cycling, Handball

Introduction: My name is Fr. Dewey Fisher, I am a powerful, open, faithful, combative, spotless, faithful, fair person who loves writing and wants to share my knowledge and understanding with you.