Project overview:
Project shows: The concept of a single page application is enforced here by using jsx pages which get swapped in/out of the main App component by the users actions. Where each page file is composed of different child components. The pages are navigated to/from each other by mainupulating the url path associated with each page. The useNavigate (move to a new url) and React Router hooks are used to accomplish this.
The main App() is composed of the following nested React Router hooks:
where each Route specifies a unique url path to a custom jsx page. There can be multiple <Routes>.
The pages are:
– AppLayout – contains the Sidebar(Logo and CityList/CountryList) and the Map components.
– Homepage – contains the PageNav header (Logo, PRICING/PRODUCT/LOGIN), some text and a custom button component with a Link to the Login page.
– Login – contains the PageNav header (Logo, PRICING/PRODUCT/LOGIN), a useState for the email and password, along with the form onSubmit function (called by the ‘Enter’ key press, or clicking on the <form… <Button> component) are directed to the login function of the AuthProvider, which uses a reducer to set isAuthorized to true/false. When this is set, the Login() component detects the change with useEffect, which will navigate/set the url to “/app” (actually /app/cities).
– PageNotFound – contains a text warning, and is assigned as the last <Route element… /> in the <Routes> list for the parent App() component. It is only called if the url path does not equal path=”cities’ or “cities/:id” or “countries” or “form”.
– Pricing/Product – contains the PageNav header (Logo, PRICING/PRODUCT/LOGIN) and a few paragraphs describing itself.
– ProtectedRoute – is used to redirect the url to the root “/” if the user login is not authorized. The convention is to wrap the main <AppLayout> component with the <ProtectedRoute> component.
The pages are lazy loaded, which means that each component is only loaded when it is needed, reducing the initial bundle size of the application.
There are also 17 child components that are used to build the individual pages. Almost all of the child components have a matching *.module.css file to style each component.
All of the Route hooks are wrapped by two context providers, one which provides access to cities data selected from the map, and one for the users login credentials. Both context providers use a reducer to provide access to, and manipulate city data.
When the map is clicked on the react-leaflet library fires off a useMapEvents event which we coded to add the event lat & lng coordinates to the url: “/app/form?lat=41.74144994967305&lng=-0.8349557818787503”. The Form component is called when the lat & lng are updated, which returns a <form …> to allow the user to add descriptive data about the city, after which a new city object is constructed and is added to the list of cities state variable using the CitiesContext reducer functionality.
Code:
- index.html
- App.js
- AppLayout.js
- AppLayout.module.css
- Homepage.jsx
- Homepage.module.css
- Login.jsx
- Login.module.css
- PageNotFound.jsx
- Pricing.jsx
- Product.jsx
- Product.module.css
- ProtectedRoute.jsx
- StartScreen.js
- AppNav.jsx
- AppNav.module.css
- BackButton.jsx
- Button.jsx
- Button.module.css
- City.jsx
- City.module.css
- CityItem.jsx
- CityItem.module.css
- CityList.jsx
- CityList.module.css
- CountryItem.jsx
- CountryItem.module.css
- CountryList.jsx
- CountryList.module.css
- Form.jsx
- Form.module.css
- Logo.jsx
- Logo.module.css
- Map.jsx
- Map.module.css
- Message.jsx
- Message.module.css
- PageNav.jsx
- PageNav.module.css
- Sidebar.jsx
- Sidebar.module.css
- Spinner.jsx
- Spinner.module.css
- SpinnerFullPage.jsx
- SpinnerFullPage.module.css
- User.jsx
- User.module.css
- CitiesContext.jsx
- FakeAuthContext.jsx
- useGeolocation.js
- useUrlPosition.jsx
- index.css