If simply reading this tutorial isn't enough for you, you can go here and write code alongside it.
In order to follow along with this tutorial, you'll need a basic knowledge of HTML, CSS, and JavaScript/ES6. You should also know the fundamentals of React, which you can learn by reading Quick Start with React.
In this tutorial we will make a simple CRUD app. We will fetch users from the remote API and you will be able to add, update or delete them.
While implementing this app we will use:
- React Material UI
- TanStack Query
- custom hooks
- React Context API
Here is a diagram of what we will implement.
As you can see, here are two sections each with its own responsibility. One for create and edit user data and another for visualize the list of users.
First, let's a component responsible for all users data on the page.
components/users.js
import { Container } from '@mui/material';
export const Users = () => {
return (
<Container
maxWidth="md"
sx={{ margin: '20px auto' }}>
</Container>
);
}
The Container
component is used to center your content horizontally.
-
maxWidth="md"
: This sets the maximum width of the container. Themd
value means that the maximum width is set to the value defined for medium-sized screens in Material-UI's theme. This is a way to make the component responsive. -
sx={{ margin: '20px auto' }}
: This is a shorthand for inline styles.sx
is a special property provided by Material-UI for customizing styles.
Then, let's implement a component to render list of users.
components/users-table.js
import {
Paper,
Table,
TableBody,
TableCell,
TableContainer,
TableHead,
TableRow
} from "@mui/material"
export const UsersTable = () => {
return (
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>Name</TableCell>
<TableCell>Email</TableCell>
</TableRow>
</TableHead>
<TableBody></TableBody>
</Table>
</TableContainer>
);
}
Let's explain the code above.
-
<TableContainer component={Paper}>
: TheTableContainer
component is used as a container for theTable
. It uses thePaper
component as its base, which gives it a Material design look with a shadow and background. -
Table
,TableHead
,TableBody
,TableRow
andTableCell
are just wrappers for native elements of the table.
Now, import UsersTable
inside Users
.
components/users.js
import { Container } from '@mui/material';
import { UsersTable } from './users-table';
export const Users = () => {
return (
<Container
maxWidth="md"
sx={{ margin: '20px auto' }}>
<UsersTable />
</Container>
);
}
And Users
inside App
.
App.js
import { Users } from './components/users';
export default function App() {
return <Users />;
}
At this moment you should see three table head sections without any data inside the table. It is an expected behaviour.
Now, let's fetch and render data about our users.
To do this, first of all we need to initialize a QueryClient
and provide it to the application through a QueryClientProvider
.
index.js
import React from "react";
import { createRoot } from "react-dom/client";
import { QueryClient, QueryClientProvider } from '@tanstack/react-query';
import App from "./App";
const queryClient = new QueryClient();
const root = createRoot(document.getElementById("root"));
root.render(
<QueryClientProvider client={queryClient}>
<App />
</QueryClientProvider>
);
Then, we need to define a layer responsible for data fetching.
api/use-users.js
import { useQuery } from "@tanstack/react-query"
import axios from "axios";
export const useUsers = () => {
return useQuery({
queryKey: ['users'],
queryFn: async () => {
const { data } = await axios.get(
'https://jsonplaceholder.typicode.com/users'
);
return data;
}
});
}
Here we utilize useQuery
hook from React Query
library inside our own custom hook useUsers
.
-
queryKey: ['users']
is a unique identifier, which is used by React Query to cache and retrieve the query's data. -
queryFn
is an asynchronous function that defines how to fetch the data. This function will be called by React Query to load the data.
Now, let's use useUsers
inside our App
component.
App.js
import { Users } from './components/users';
import { useUsers } from './api/use-users';
export default function App() {
const { isFetching, isError, data } = useUsers();
if (isFetching) {
return <div>Loading...</div>;
}
if (isError) {
return <div>Error</div>;
}
return <Users users={data} />;
}
Then, let's handle users
inside Users
component and pass it down to UsersTable
.
components/users.js
...imports
export const Users = ({ users }) => {
return (
<Container
maxWidth="md"
sx={{ margin: '20px auto' }}>
<UsersTable users={users} />
</Container>
);
}
Finally, we can render our users
.
components/users-table.js
...imports
export const UsersTable = ({ users }) => {
const renderUsers = (users) => {
return users.map(user => {
return (
<TableRow key={user.id}>
<TableCell>{user.name}</TableCell>
<TableCell>{user.email}</TableCell>
</TableRow>
);
})
}
return (
<TableContainer component={Paper}>
<Table>
<TableHead>
<TableRow>
<TableCell>Name</TableCell>
<TableCell>Email</TableCell>
</TableRow>
</TableHead>
<TableBody>{renderUsers(users)}</TableBody>
</Table>
</TableContainer>
);
}
To be continued...
Top comments (2)
That link to the code-along site is pretty neat. That's a great way to learn.
Thank you ❤️