StackTrek Quiz
Report Bug
ยท
Request Feature
Table of Contents
A small but feature-rich app that lets you keep track of your contacts as found here: https://reactrouter.com/en/main/start/tutorial.
In addition to basic routing, React Router comes with functionality that let you carry out CRUD operations on the client side.
React Router defines route in a declarative way (i.e the same way you write React components or declare and define a JavaScript object).
This can be done in two (2) ways:
- A Route Config Object:
const router = createBrowserRouter([
{
path: "/",
element: <Home />
},
{
path: "/about",
element: <About />
},
{
path: "/some-other-component",
element: <SomeOtherComponent>
}
...
]);
- JSX Routes:
The more preferred method by many:
<Routes>
<Route path="/" component={<Home />}>
...
</Routes>
If you think about it, navigating to a route and fetching data from an API go hand in hand for pages that need to pull data from a server like say, you guessed it, a contact list application!
If you are going to build an application that fetches data from a server database through an API endpoint, you're likely going to want to write or update or even delete data in the database through other endpoints.
The team behind React Router thought it befitting to provide two (2) clever pieces of technology to help with these all too familiar CRUD operations known as a loader
and an action
.
A loader is a function that you write which makes a request for data for your page while an action is both a function you write to write or delete data and a route that your <Form />
component, also provided by React Router, sends its formData
. formData
is what a vanilla HTML form sends to the path specified in the action
attribute when it is submitted - this is standard web technology.
I have placed all the loaders and actions in ./src/utils/functions.ts
(with namiming convention; {component}Loader/Action
to distinguish loaders and actions from one another) just to have them all in one place.
Mapping them to the CRUD operations, starting with Read, they would be:
Read
// ./src/utils/functions.ts
// `Request` is a standard type as defined by web 2.0 specifications
export async function rootLoader({ request }: { request: Request }) {
const url = new URL(request.url);
const q = url.searchParams.get("q");
const contacts = await getContacts(q || "");
return { contacts, q };
}
The <Root />
component can use this loader:
// ./src/routes/root.tsx
export default function Root() {
const { contacts, q } = useLoaderData() as Awaited<ReturnType<typeof rootLoader>>;
...
}
Because in the route config object, we have specified it to be the loader for this component when its route is visited:
// ./src/main.tsx
import { createBrowserRouter, RouterProvider } from "react-router-dom";
import {
rootLoader,
...
} from "./utils/functions";
const router = createBrowserRouter([
{
path: "/",
element: <Root />,
loader: rootLoader,
action: rootAction,
errorElement: <ErrorPage />,
children: [
...
],
},
]);
To get a local copy up and running follow these simple example steps.
You need to have npm
installed on your computer in order to be able to install and run the project.
- npm
npm install npm@latest -g
- Clone the repo
git clone https://github.com/Chizaram-Igolo/contact-list.git
- Install NPM packages
cd contact-list && npm install
- Run the Project
npm run dev
- Navigate to
http://127.0.0.1:5173/
(or the exposed port) on your favourite browser