In our previous article, we introduced Recoil to our app. In this article, we’ll add a more complex piece of state, an array of live games currently underway. We’ll also add a button to add new games to our list.
Creating The Atom
The first step is to create an atom that will hold the state of the current games. The games will be stored in an array, with each element containing a high-level overview of the game details.
The details we are storing are as follows:
the id of the game
the name of the table
the number of players currently playing
The time the table has been active.
Of the above values, we will not be displaying the id value. We can use this id as the key for our table in React.
We begin by creating a folder that will be used to hold Recoil Atoms. This folder is named state for the time being. In this folder, we will create a file named LiveGamesState.js. This file will contain one exported value named liveGamesState.
Using the atom() function from the Recoil package, we can create our array and export it for use by other components. The default value is set to include five made-up tables. This will do for now, as we are just using this to demonstrate using state in our application.
The LiveGameState.js File
The following is the result of the above considerations when generating an Atom for the live games:
Our LiveGamesTable component currently displays the live games in a table. It uses a seed function to create five rows to use as sample data.
Let’s replace this seed function and use our newly minted Atom as the data source for the table.
//const data = generateTablesData(5);
const data = useRecoilValue(liveGamesState);
That is all required (other than importing useRecoilValue from recoil). If you run the application at this stage, you will see no difference from what we had in the previous article.
Updating The Atom
Now we can read the data in the LiveGamesState Recoil state. The next step is to be able to add new games to the list.
Let’s create a button in the NavBar that will add new games to our list.
Note: The addGame function will keep adding the same data to the table. This means that React will complain about the same key being used multiple times in the table. This is OK for now.
Running the app with this button enabled looks like this:
Conclusion
As demonstrated, we can add complex state objects to our application with just a few lines of code. Recoil makes global state management easy to understand and implement.
Don’t forget to look at our other MUI and React articles!
Continuing from the last article, we are at a point where we want to build the components that a logged-in user can see. But we don’t want to start adding complex authentication handling to our application yet. This can be done by adding global state management system like Recoil to our application.
Introducing Recoil
Recoil is the state management library built by the Meta (Facebook) team. In the Card Games app, we’ll implement Recoil to manage the logged-in status of our users and some details about the games currently being played.
Considering it is still reasonably new (2020) to the public, you may prefer to use another tool for your applications.
Setting Up State With Recoil In Our App
To begin, we need to install Recoil:
npm install recoil
Once installed, we must wrap our application component with the Recoil component. This allows Recoil to be present on all child components. The Recoil wrapping component is called RecoilRoot.
Let’s start with a simple boolean value to denote whether a user is logged in. In Recoil, this will be done by creating an Atom. An Atom represents state in Recoil.
To create an Atom, you call the atom() function and pass a JSON value as the parameter. For example, our logged-in state can be represented as an atom like this:
import { atom } from 'recoil';
const loggedInState = atom({
key: 'loggedInState',
default: false,
});
Now that we have the loggedInState Atom ready to go, we need two more parts to make the Atom useful:
a way to read the current value of loggedInState
a way to update/set the value of loggedInState
Reading The Value Of A Recoil Atom
Use the hook useRecoilValue to retrieve an Atom’s value and subscribe your component to re-render if the value changes.
If we continue with our loggedInState Atom from above, you can get access to its value like this:
const loggedIn = useRecoilValue(loggedInState);
You can then use the variable loggedIn within your component to drive the UI.
Setting The Value Of A Recoil Atom
Setting the Atoms value is also done by using a hook. This hook is called useRecoilState. This hook will return the state value and the function to set the state value. Much like the useState hook does in React.
Let’s update our above example using the useRecoilState hook:
That is all that we need to do to save the logged-in status of our users. Let’s look at hiding the currently played games table for users that aren’t logged in.
Using Recoil Atoms In Other Components
We have a component:
<LiveGamesTable />
This component lists all the games that are currently happening. I will show this table when a user logs in.
Luckily, we now have an Atom that holds the logged-in status of users.
Let’s use this status to hide or show the table as appropriate.
Remembering the hooks mentioned above, our LiveGamesTable component must use the useRecoilValue hook to ascertain the users logged in status.
So, let’s start by importing what we need into the LiveGamesTable component:
import { useRecoilValue } from 'recoil';
import { loggedInState } from './App';
We now need to get the logged-in value from the loggedInState Atom. We can put this at the start of the LiveGamesTable function for use later:
function LiveGamesTable() {
const loggedInStatus = useRecoilValue(loggedInState);
And finally, we can do a boolean shortcut to only display the table to logged-in users:
{loggedInStatus &&
<Box...
And there you have it. We now have a scaffold for adding global state to our application. In the next article, I will add a more complex data structure (the details of the games currently being played) to the global state.
Thanks for reading! If you want to catch up with me directly, reach out on Twitter. And as always, you can find the source code on GitHub
P.S. You can see where this project started in my other article here
In this article, we’ll customise the look and feel of the MUI Card Game site that we started previously. The process of theming a site using MUI involves two main steps:
Create a theme object
Wrap components with ThemeProvider that you want to use for your theme.
This tells us how to create a theme, but what kind of customisations should you look at when designing your theme?
Theme Considerations
The three most important considerations (according to me) when setting up a theme in MUI are:
Colours
Spacing
Typography
Colours
MUI works off primary and secondary colours. Setting primary and secondary colours in MUI can help personalize your site and make it more engaging and accessible to your users. It’s important to choose colours that suit your brand, content, and target audience and ensure that the colours are consistent across all your site’s components.
Spacing
Using a consistent spacing scheme across your site, you can personalise the site to your brand or aesthetic. Spacing can also help with accessibility issues. For example, if your buttons have sufficient space between them, it is easy for users to click the correct button.
Typography
Typography is really important when styling your theme. Using the same typography across your site can help with branding and aesthetics.
With these considerations in mind, let’s consider creating the theme in MUI.
Creating A Theme Object In MUI
To set a theme across your site in MUI, you must create a theme object that you wrap around your root component with a ThemeProvider component.
You can then export the theme object to wrap around other components in your application (in this case, we’ll wrap the entire site in our custom theme).
The Theme Properties
I will set the site’s typography, spacing and colours for this example. The documentation on how to set a custom theme can be found here.
Spacing
For this theme, I want to make it compact, as the plan for the site has tables of games being played online, user stats and more. So screen real estate is at a premium in most views.
We add a spacing key/value pair, with a value less than 8, to the JSON theme to make the site more compact. The reason it’s set to less than 8 because the default theme layout spacing value in MUI is 8.
Colours
I have picked two colours, green and red, as my primary and secondary colours, respectively. For the primary,I will use #386641, and for the secondary, I will use #bc4749.
These colours should hopefully help give the site the feel of a casino. The best part is that we change the theme colours later, and the site will update accordingly.
Typography
I want to use a clean, easy-to-read font, so I have chosen the font Lato for this purpose (with a fall back to sans-serif).
Coding The MUI Theme
Now that we’ve decided on how we want the overall theme to look, we create the JSON object that will be the source of our theme.
The JSON is fairly self-explanatory. We are setting the colours in the pallet. Spacing is set on the base level, as is typography. With just a few lines of JSON, we can now style our entire site without adding classes to each component to perform the styling.
MUI Component Styling
In addition to the above styling, you can style MUI components to your liking. To demonstrate this, we’ll now add a components element to our JSON data that will stripe alternating rows of MuiTableRow instances, colour the head of the table and add a custom bottom border to each row.
The official MUI documentation lets you learn about the component API and possible theme settings.
How it looks with our theme
As you can see, it’s a pretty basic site, but it shows the main theme settings we’ve applied. The two buttons under the table use colours primary and secondary. The table demonstrates the row striping and bottom border that we’ve applied.
To contrast, let’s remove the ThemeProvider token and look at the same site.
As you can see, the spacing between the buttons is larger, the table is plain, and the default colour scheme has been reverted. Even the small customisation our theme provides makes a big difference already.
Conclusion
Thank you for reading this post on theming with MUI. If you like what you’ve read or want to discuss anything, you can find me on Twitter.
The Box component in MUI differs from a div in that it is a React component that can take the sx prop to access the MUI system properties. This article will compare the MUI Box vs HTML div.
Let’s start with the MUI documentation description of the Box component:
The Box component serves as a wrapper component for most of the CSS utility needs.
https://mui.com/material-ui/react-box/
We can easily understand that a wrapper component drives styling or overarching information down to child components. The difficulty in this description is understanding the “CSS utility needs“.
But first, let’s look at what the Box component outputs in HTML.
What HTML Does Box Output?
To understand the CSS utility needs, it’s important to understand what Box components output when rendering. Let’s start with a simple example:
<Box>Some text</Box
Outputs:
<div class="MuiBox-root css-0">Some text</div>
The Box component outputs a div but sets the class to MuiBox-root. This means that all styling will come from MUI for the elements contained within our Box. This is the first part of CSS utility needs
MUI System Style Functions
If you read further, the documentation mentions that:
The Box component packages all the style functions that are exposed in @mui/system.
An example of a style function is bgColor. This is a shorthand version of the background-color CSS property. The following code is a good example of using bgColor. Notice that we use this style function within the sx prop.
<Box sx={{ bgcolor: "red" }}>Text with red background</Box>
Using Theme Mapping With The MUI Box Component
The biggest benefit of using the Box component, at least in my opinion, is the access to the theme mapping. This allows the developer to access theme options like palette or spacing. Here is a quick example showing how to use these theme options with the box component.
<Box sx={{ bgcolor: 'info.light', p: 5 }}>Text with blue background</Box>
The above code uses the palette setting of info.light, the blue we see above. The p: 5 sets the padding element to 5, as shown in the space around the text in the image above.
The image below shows the theme properties tree where we select the info.light property.
Tree item showing the info light property of the default theme
It’s worthwhile looking at the default theme options in the documentation. It can be found here.
The alternative way to get a standard div to access the system properties would be to import them into your file and use the variables to drive the styling. The above method circumvents the need for all that and can focus on your design.
Conclusion
There is not much more to the Box component than this. It allows you to wrap your elements so that they inherit the MUI theme, as well as allowing you to select directly from the system properties. Hopefully, this helps you understand the MUI Box vs HTML div.
In this article, I will attempt to refactor the PlayingCard component that we built in this article. The refactor will convert the component from plain React to MUI. Once we’ve updated the card, we can import this into our Card Game app and use it as the base playing card for each game.
If you’re looking for the final product, you can find it on GitHub here.
Looking at the final PlayingCard component, we can make a few obvious updates.
The first visual change will be the drop shadows that give the card thickness. MUI offers the paper container property that will give a nice paper feel to our card.
Using The Paper Property
In our PlayingCard component, the card was represented by a div element. Let’s change this to a Paper component. We must replace the opening and ending tags from div to Paper.
Once we’ve updated the tags, we must remove the box shadow style property.
If we were to run the code at this point, you would see the playing card with no shadows looking the same as it did before. This is what we want to see.
Using the elevation attribute, we can recreate the complex box shadow styling we removed earlier. The elevation attribute is an integer (number) from 0-24. 24 is the highest elevation we can give our paper component. Let’s add this to our card now. The Paper component in our code now looks like this:
The next alteration we can make is using Typography instead of standard HTML text elements. We start by making sure we are importing the Roboto font. Following the instructions in the Typography documentation, we need to install the @fontsource/roboto NPM package.
npm install @fontsource/roboto
Once we’ve installed roboto, we update the h1 elements and replace them with Typography components. For example, our top h1 tag becomes:
Finally, we can update the div containers in the PlayingCard component to use the MUI Box component instead. After replacing all divs with Boxes, we can update the style attributes to use the MUI sx prop.
And that should do it for now. We’ve taken a plain React component and applied MUI fundamental components. This may not seem like a big deal, but it might become bigger once we start theming our card game site.
In this article, we’ll build a basic UI for a card game (remember the playing card component we built earlier) using React with MUI Core. This UI will showcase the following:
In short, MUI core is a set of React components that can be used as the foundation blocks of your design system. Furthermore, these components have been designed with accessibility always in mind (which is super important).
MUI implement’s Googles material design.
We will follow the instructions from the MUI website to start building our application, but first, we’ll need to create the base application. For this, we can use the create-react-app script for bootstrapping a basic React app that we will then style using MUI Core.
Creating The React App Using create-react-app
npx create-react-app mui-card-game
This will create a directory with our React app ready to configure.
Installing MUI Core
Installing MUI core is done by using npm as follows:
Because MUI uses the Roboto font, we must import it into our application. We start by installing @fontsource/roboto:
npm install @fontsource/roboto
Once you’ve installed Roboto, we must import the fonts at our app’s entry point. Because we are using create-react-app, our entry point will be in src/index.js. You need to add the following to add all the variations of Roboto that MUI uses:
With material, emotion and Roboto now configured for our application, we must add Icons. This is another npm package.
npm install @mui/icons-material
Cleaning Up create-react-app
Lastly, we need to remove any styling with create-react-app in our setup. This is done by removing the two CSS files in the src folder: index.css and App.css, and references to these files.
InApp.js, remove the following line:
import './App.css';
And in index.js, remove this line:
import './index.css';
If you start the site now:
npm start
You will see the React icon with some text underneath (we’ve removed the style sheets, so the result won’t look good):
create-react-app with styling removed
Next, we can remove the contents of App.js and replace them with our new code.
Adding A NavBar With React and MUI Core
Let’s clear out most of the contents of App.js, so we are left with this:
In MUI, you must add an AppBar that will act as our NavBar. The easiest way to get started is to head over to the MUI documentation for AppBar and grab the closest example to what we need. For this demo we can select the basic AppBar example.
If you copy the code, we can create a new component in our app in a new file called NavBar.js. Populate this file with the below code (The only difference from the MUI documentation is that I have renamed the function name to NavBar):
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import MenuIcon from '@mui/icons-material/Menu';
export default function NavBar() {
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="menu"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
News
</Typography>
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
</Box>
);
}
Installing Dependencies
To use the above code, you’ll need to install @mui/icons-material NPM package:
npm install @mui/icons-material
In App.js, import the NavBar component and render this component in the return statement as follows:
import NavBar from "./NavBar";
function App() {
return <NavBar />;
}
export default App;
If we run the code, we will see the AppBar looking like this:
Basic AppBar (from MUI documentation)
Let’s tweak the navbar to have a sign up button and to change the text News to Card Games:
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import MenuIcon from '@mui/icons-material/Menu';
export default function NavBar() {
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="menu"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Card Games
</Typography>
<Button color="inherit">Login</Button>
<Button color="inherit" variant="outlined">Sign Up</Button>
</Toolbar>
</AppBar>
</Box>
);
}
Updated AppBar
We need to add a signup form to our site. Let’s do this using a modal form where users can enter their email addresses and password. The easiest way is to return to the MUI documentation and find the modal examples.
When we search for Modal in the documentation, you will see a note saying that if you want to use a modal component, you probably want to use the Dialog component. So based on this, we’ll move forward using the Dialog component.
In the documentation for Dialog, there is an example of a Form Dialog. Let’s use this as our base for the signup form. We’ll call our component SignUpForm and put it in a file named SignUpForm.js
import * as React from 'react';
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
export default function SignUpForm() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button color="inherit" variant="outlined" onClick={handleClickOpen}>
Open form dialog
</Button>
<Dialog open={open} onClose={handleClose}>
<DialogTitle>Subscribe</DialogTitle>
<DialogContent>
<DialogContentText>
To subscribe to this website, please enter your email address here. We
will send updates occasionally.
</DialogContentText>
<TextField
autoFocus
margin="dense"
id="name"
label="Email Address"
type="email"
fullWidth
variant="standard"
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={handleClose}>Subscribe</Button>
</DialogActions>
</Dialog>
</div>
);
}
There are two notable differences between the sample code and the code above. This ensures the button inherits the colour from its parent and the component’s name. The highlighted line shows these differences.
Adding The Dialog To The NavBar
Now we have a button component displaying a modal form for the user to enter an email address. The next thing to do is to add the component to the NavBar. We’ll replace the current Sign Up button we placed earlier.
import * as React from 'react';
import AppBar from '@mui/material/AppBar';
import Box from '@mui/material/Box';
import Toolbar from '@mui/material/Toolbar';
import Typography from '@mui/material/Typography';
import Button from '@mui/material/Button';
import IconButton from '@mui/material/IconButton';
import MenuIcon from '@mui/icons-material/Menu';
import SignUpForm from './SignUpForm';
export default function NavBar() {
return (
<Box sx={{ flexGrow: 1 }}>
<AppBar position="static">
<Toolbar>
<IconButton
size="large"
edge="start"
color="inherit"
aria-label="menu"
sx={{ mr: 2 }}
>
<MenuIcon />
</IconButton>
<Typography variant="h6" component="div" sx={{ flexGrow: 1 }}>
Card Games
</Typography>
<SignUpForm />
<Button color="inherit">Login</Button>
</Toolbar>
</AppBar>
</Box>
);
}
Now when we click the Sign-Up button, we’ll see the following:
Subscribe Dialog
We can tweak the contents of the Dialog for our needs. We want:
Users to sign up and not subscribe
To get users’ names when signing up.
Therefore we need more form fields in the Dialog and change some of the text.
Let’s look at the code of our SignUpForm component now that we’ve updated the text and fields.
import * as React from 'react';
import Button from '@mui/material/Button';
import TextField from '@mui/material/TextField';
import Dialog from '@mui/material/Dialog';
import DialogActions from '@mui/material/DialogActions';
import DialogContent from '@mui/material/DialogContent';
import DialogContentText from '@mui/material/DialogContentText';
import DialogTitle from '@mui/material/DialogTitle';
export default function SignUpForm() {
const [open, setOpen] = React.useState(false);
const handleClickOpen = () => {
setOpen(true);
};
const handleClose = () => {
setOpen(false);
};
return (
<div>
<Button color="inherit" variant="outlined" onClick={handleClickOpen}>
Sign Up
</Button>
<Dialog open={open} onClose={handleClose}>
<DialogTitle>Sign Up</DialogTitle>
<DialogContent>
<DialogContentText>
To sign up to this website, please enter your personal details here.
</DialogContentText>
<TextField
autoFocus
margin="dense"
id="email"
label="Email Address"
type="email"
fullWidth
variant="standard"
/>
<TextField
autoFocus
margin="dense"
id="name"
label="Full Name"
type="text"
fullWidth
variant="standard"
/>
</DialogContent>
<DialogActions>
<Button onClick={handleClose}>Cancel</Button>
<Button onClick={handleClose}>Sign Up</Button>
</DialogActions>
</Dialog>
</div>
);
}
As you can see, there is now another text field for users to enter their full names into. We’ve also altered the description a little to suit our needs. The output of the above code looks like this:
Sign Up Dialog
Creating The Current Games Table
Now that we have completed the faux login button and signup form, we will add a table showing a list of all the current games currently being played online. We will use dummy data to populate the table to show how easy it is to get a decent-looking table going with MUI.
The table structure is simple in MUI. Here is the code that will build a table:
In the above code, I’ve used the component type to be paper for styling purposes. The rest of the code resembles an HTML table quite closely.
In the table body section, I used an array and mapped out each row based on each element in the array. The resulting table looks like this:
Current Games Table
Putting It All Together
Now that we have our header and table, we can look at the entire page as a whole:
The following image shows the site after the signup button is clicked:
After the Sign Up button clicked
Conclusion
With just a little bit of customisation, we’ve generated a basic page structure with MUI that looks professional and is accessibility friendly. This goes to show how powerful using a UI framework can be. It also shows how well React and MUI Core work together. Thanks for reading!
This is a library for managing state in JavaScript applications. It helps you keep track of changes to your data and automatically updates your user interface when those changes occur.
Think of it like a magic assistant sitting in your code and watching everything happening. Whenever something changes, it waves its wand and updates your app accordingly. You don’t have to worry about manually updating the interface or keeping track of all the different pieces of data. MobX takes care of it for you.
This makes it much easier to build complex applications. Because you can focus on writing the code that makes your app work. Rather than worrying about the plumbing that connects everything. With MobX, you can create reactive, responsive apps that feel snappy and fast.Eeven when dealing with large amounts of data.
Also known as Material-UI, this is a popular open-source UI component library for React based on Google’s Material Design principles. Providing pre-built and customizable UI components such as buttons, forms, icons, typography, and more. Developers can use these to quickly build modern and visually appealing web applications.
It follows a component-based architecture, allowing developers to easily create reusable and composable UI components. It also provides theming support, allowing developers to customize the look and feel of their applications. This is done by defining their colour palette, typography, and other design elements.
MUI Core is widely used in the React community and has a large and active community of contributors. It is continuously updated and improved, with new features and components regularly added. Licensed under the MIT License, making it free to use and modify in commercial and non-commercial projects.
A popular CSS-in-JS library for React that allows developers to write CSS code inside their React components. It provides a way to style components more modularly and reusable way. The styles are encapsulated within the component. Therefore they don’t affect other components of the application.
This library allows developers to define styles as JavaScript functions or tagged template literals. These styles are then applied to the corresponding components using a higher-order component (HOC) or a styled component factory function. This makes it easy to create responsive and dynamic styles based on props or state.
It also supports server-side rendering, theming, and automatic vendor prefixing. Making it a versatile and powerful tool for styling React components.
One of the advantages of using this is that it allows developers to write CSS in a more maintainable way. By keeping styling close to the components they style, it becomes easier to reason about how style changes will affect the component and its children. Additionally, this library allows developers to use all the power of JavaScript to create dynamic and complex styles. This makes it a very flexible and powerful tool for building modern web applications.
Could you think of how styled components could be used in our Card component?
React Icons is a popular open-source library that provides a set of customizable icons for use in React applications. It offers a wide range of icons from popular icon sets such as FontAwesome, Material Design, and Ionicons, as well as custom-designed icons.
React Icons provides a simple and flexible API that allows developers to add icons to their components easily. It supports multiple sizes, colours, and styles for each icon and provides different ways to import and use icons depending on the developer’s preferences.
Some of the advantages of using React Icons include the following:
Customizable: React Icons provides a simple and flexible way to customize icons by changing their size, colour, and style.
Easy to use: The library provides a straightforward API that makes adding icons to React components easy.
Lightweight: The library is lightweight and does not require any additional dependencies.
Widely used: React Icons is a popular library with a large and active community of contributors. Making it a reliable and well-maintained option for adding icons to React applications.
Summing up, React Icons is a great tool for developers who need to add icons to their React applications in a flexible and customizable way.
React Query is a popular open-source library for managing server-state and fetching data in React applications. It offers a simple and intuitive API for data fetching, caching, and synchronization, making handling complex data requirements in your React components easier.
React Query offers key features that make it a powerful tool for managing data in your React applications. In particular, these include:
Query caching: React Query automatically caches your API responses. This can improve the performance of your application and reduce the number of network requests.
Data synchronization: React Query provides built-in support for real-time polling, and optimistic updates, making it easier to keep your application in sync with your backend.
Error handling: React Query offers robust error handling, built-in support for retrying failed requests, handling stale data, and more.
Pagination and infinite scrolling: React Query provides built-in support for pagination and infinite scrolling, making it easy to handle large data sets.
Overall, React Query simplifies data fetching and management in React applications, helping developers to build more performant and reliable user interfaces.
React Table is a popular open-source library for building data tables in React applications. It provides a flexible and customizable API for rendering tables with large amounts of data, allowing developers to create powerful and performant user interfaces.
Some of the key features of React Table include:
Sorting and filtering: React Table provides built-in support for sorting and filtering data, making it easy to display large data sets meaningfully.
Pagination: React Table supports pagination, allowing you to display data in smaller, more manageable chunks.
Row selection: React Table supports row selection, making implementing features like bulk actions and editing easy.
Custom rendering: React Table provides a powerful API for customizing your table cells, headers, and more rendering.
Server-side rendering: React Table supports server-side rendering, allowing you to render your tables on the server and send the HTML to the client for improved performance and accessibility.
Evidently, React Table is highly customizable and extensible, making it a popular choice for building data tables in React applications. It is also compatible with various data sources, including JSON, CSV, and REST APIs.
Create React App (CRA) is an open-source tool created by Facebook for setting up a modern React application with zero build configuration. It provides a simple and streamlined way to create and manage a new React project, allowing developers to focus on building their applications instead of worrying about tooling and configuration.
Create React App sets up a development environment for React that includes many of the commonly-used tools and technologies, such as:
Webpack: A module bundler that helps to bundle all of the assets, including JavaScript files, CSS files, and images.
Babel: A JavaScript compiler that allows developers to write modern JavaScript code and transpile it to be compatible with older browsers.
ESLint: A linter that helps to enforce code quality and consistency.
Jest: A testing framework that provides a simple and easy-to-use API for testing React components and JavaScript code.
Hot Module Replacement: A feature that allows developers to see the changes they make in real-time without manually refreshing the browser.
Create React App also provides several configuration options, allowing developers to customize their development environment to suit their needs. It supports CSS modules, environment variables, code splitting, and more.
Overall, Create React App is a powerful tool that makes it easy to set up a new React project with minimal configuration, allowing developers to focus on building their applications instead of managing tooling and configuration.
React Motion is a popular open-source library for building animated user interfaces in React applications. It provides a simple and intuitive API for creating complex animations and interactions, allowing developers to create fluid and engaging user experiences.
React Motion is based on the principles of physics-based animation, which means that a set of parameters such as velocity, acceleration, and damping drives animations. This approach allows for more natural and realistic animations that respond to user input and change over time.
Some of the key features of React Motion include:
Spring-based animations: React Motion provides a simple and powerful API for creating spring-based animations, which can be used to animate everything from simple transitions to complex interactions.
Customizable animation parameters: React Motion allows developers to customize the parameters of their animations, including things like spring stiffness, damping, and velocity.
Performance optimizations: React Motion is designed to be highly performant, with features like batched updates and optimized rendering to minimize the impact on the user interface.
Easy integration with React: React Motion is designed to work seamlessly with React, allowing developers to build complex animations and interactions using the same familiar API and programming model.
Overall, React Motion is a powerful tool for building animated user interfaces in React applications, allowing developers to create engaging and interactive experiences that respond to user input and change over time.
Enzyme is a popular open-source JavaScript testing utility created by Airbnb for testing React components. It provides a set of intuitive and flexible APIs for testing React components’ behaviour and state changes, making it easy to write comprehensive and reliable tests for React applications.
Enzyme offers several features that make it a powerful tool for testing React components, including:
Shallow rendering: Enzyme provides a shallow rendering API that allows developers to test a component in isolation without rendering its child components.
Full DOM rendering: Enzyme also provides a full DOM rendering API that allows developers to test a component in the context of its parent and child components.
Powerful selectors: Enzyme provides a set of powerful selectors that allow developers to find and manipulate components within their tests easily.
Snapshot testing: Enzyme supports snapshot testing, allowing developers to easily capture the output of a component and compare it against a previously saved snapshot.
Easy integration with other testing frameworks: Enzyme can be easily integrated with others like Jest, Mocha, and Chai, making it a versatile and flexible tool for testing React applications.
Enzyme is a powerful testing utility that makes writing comprehensive and reliable tests for React components easy. Its intuitive and flexible API, along with its support for shallow rendering, full DOM rendering, and snapshot testing makes it a popular choice among developers for testing React applications.
A popular open-source framework for building server-side rendered React applications. It provides features and conventions for building modern web applications, including automatic code splitting, server-side rendering, and static site generation.
Some of the key features of Next.js include:
Server-side rendering: Next.js provides built-in support for server-side rendering, allowing your application to render on the server and send HTML to the client for improved performance and SEO.
Automatic code splitting: Next.js automatically splits your code into smaller chunks, allowing your application to load faster and improve performance.
Static site generation: Next.js allows you to generate a static version of your application, making it easy to deploy to a static hosting provider like Netlify or GitHub Pages.
File-based routing: Next.js provides a simple and intuitive file-based routing system that makes creating pages and routes in your application easy.
API routes: Next.js provides a built-in API route system, making creating API endpoints in your application easy.
CSS-in-JS support: Next.js provides built-in support for popular CSS-in-JS libraries like styled-components and emotion, making creating dynamic and responsive styles in your application easy.
All in all, Next.js is a powerful and versatile framework for building modern web applications. Its built-in support for server-side rendering, automatic code splitting, static site generation, intuitive file-based routing system, and support for popular CSS-in-JS libraries make it a popular choice for building scalable and performant React applications.
Conclusion
This list is not meant to be an exhaustive list of must-know React packages, but React developers need to understand the type of packages available. If this list has helped you, please share the article! Thanks for reading!
If you have tried to write your React components without a local web server, you may have encountered an issue where the React dev tools cannot access local files.
In these instances, there won’t be an error in your console, but you will see a message like the following:
Download the React DevTools for a better development experience: https://reactjs.org/link/react-devtoolsYou might need to use a local HTTP server (instead of file://): https://reactjs.org/link/react-devtools-faq
To get the React Dev Tools working with local files, you need to allow the extension to have access to them. This is done in the Manage Extension section of the developer tools. You can access this by clicking the three vertical dots (vertical ellipsis?) next to the extension name. You will get a drop-down menu like the one below where you can click the Manage Extension menu item.
Once you click this, you will be presented with a list of options for the extension. You are looking for the option Allow Access to file URLs. If you turn this on, you can use the developer tools on local React components.
You can find more information on the React dev tools extension, precisely this issue, here.
Interestingly, in Firefox (on macOS, in my case), I didn’t have to add any permissions to allow the dev tools to work with local files. There is no option to allow dev tools to work with local files, so it seems intentional that it works out of the box with no user feedback required.
Don’t forget to check out some of our other articles on React:
Can you build a React app without using the NPM (node package manager) or Yarn (Yet Another Resource Negotiator)? Yes, you absolutely can. React is a JavaScript library you can manually import into any web page. Let’s look at building a simple React component without npm.
This only intends to show what React is doing without JSX and Babel. It is also an excellent way to add React to a page on a site where you only have a limited need for React components.
You should also note that the first few steps of this process are mentioned in greater detail in the React documentation found here.
The first step is to create the HTML page for your site. Let’s call this index.html.
The two scripts included are the development versions of the React library. These are not intended for production.
Creating A React Component Without NPM
With the boilerplate HTML complete, the next thing we need to do is create our component. Let’s create a new JavaScript file where we will code our component. We can call this file Feedback.js
If you want to see a complete React component written from scratch, you can see that here.
The Feedback component will be a button at the bottom right of the screen and pop out a text area for comments. The idea is to show how to add a useful React component without NPM.
The first step is to create a function named Feedback that returns an element. You can return an element using the createElement function in the React library.
The first createElement parameter is type. This type can be a regular HTML element or a React component. As we create a button component, we’ll use ‘button’ for the type parameter.
The second parameter is props. We’ll alert the user when the button is clicked for our initial implementation. This means we can pass an onClick function as a prop to our component.
The third parameter is an option children parameter. Let’s leave this blank initially.
Now that we have a basic component defined, we need somewhere to show it. To do this, you need to add an element in the HTML that will be the location of where the component will be shown.
Let’s create a div element that will act as the entry point to the React tree of components. We will give the div an id attribute so that we can inject our React component.
To use the new div as the entry point, we need to update our JavaScript. We need first to get a reference to the div and then tell React to create a root node at this div. Finally, we need to render the component. This is done with the following JavaScript:
If we open our index.html file in a browser, you will see the following:
A More Complicated React Component Without NPM
Using React without NPM doesn’t mean the components must be entirely simple. For our feedback component, we currently use a button element. Let’s change this to a div element containing our button and the text area for users to leave feedback comments.
The following code is a complete component built off the createElement function:
Let’s recap what we want the Feedback component to do. Firstly, when the user clicks the button, the text area should become visible for users to enter feedback. Secondly, the user enters their feedback. Thirdly, they can click the button to submit it. Pretty straightforward.
Using State With React.createElement
The start of the Feedback function now uses React.useState to add state to the component. These state values relate to the colour and text of the button, the text of the text area and whether the text area is currently visible. I’ve highlighted all uses of state throughout the component.
Using The Children Parameter Of React.createElement
The Feedback component is a div element with textarea and button as its children. I have used React.createElement to create the children. The state of the Feedback component drives these children. You can see this in lines 36-37 and 51-62.
Lines 36-37 manage the text in the textarea element. Lines 51-62 manage the visual state and what happens when clicking the button.
CSS Of the Elements
The CSS of the elements are pretty basic. I have fixed the position of the Feedback component to the bottom right of the screen. The remaining styling set is there to make the elements look nice.
To highlight this fixed position, I have added some auto-generated lorem ipsum text to make the page scroll.
The Final Product Of A React Component Without NPM
This is what the button looks like on a page with some text.
Can I Use JSX Without NPM?
Yes, you can use JSX without NPM. Let’s update the above component to use JSX.
Firstly, we must add the babel source to our script section (before our component).
We briefly examined what components are in React in the “What Is React?”. This article will show how the process of creating a React component, including managing state, props, styling and more. As you work through the article, you will see how a component goes from concept to code. Let’s begin!
If you want to jump straight to the source code, check it out on GitHub here
The Playing Card
The component that we’ll be creating today is a playing card component. Firstly, we need to note down all the characteristics of the playing card we want to emulate in the UI. Namely:
Playing cards are two-sided, face up and face down
what suit the card is
the value of the card
the face side of the card can be read upside down and right side up
playing cards are rectangular with slightly rounded edges, with the vertical edges being longer than the horizontal edges
As we are just building the UI component, the card’s value can be represented by a string value, and the game engine can convert the picture cards to their appropriate value.
Now that we know what attributes we want the playing card to have, we can start building the component.
Naming The Component
In this instance, the name of the React component is self-evident, PlayingCard. This is not always the case, and it can often become difficult to name React components in an application where you are trying to be unambiguous and unique in your naming. For example, if our application used multiple playing card decks, then PlayingCard might not be descriptive enough and might also get in the way of naming other decks cards.
Now that we know the name, we need to build a function PlayingCard that will return the visual representation of the playing card.
Writing The Function
Creating a component in React is done by creating JavaScript functions with JSX expressions mixed in. Let’s create a file for our new component:
Now that we have a file for the component, we write the function:
function PlayingCard() {
return (
<p>Playing Card</p>
)
}
This is a perfectly fine function. It doesn’t do anything except return the HTML paragraph with the text Playing Card. Here is the output:
Next, we need to add the data properties to the PlayingCard. We will start with the suit and the value of the card.
Adding Props To The Component
For this component, we will pass the suit and value of the playing card from the parent of the card. We use props to pass values into a React component. Props are parameters that are passed into our component function.
Our function signature will change with the props argument being passed in.
function PlayingCard(props) {
return (
<p>Playing Card</p>
)
}
Defining The Props Component
The props object, in this case, contains the suit and value of the card. So an example of the props object would look like this:
const props = {
suit: "Hearts",
value: "10"
}
We can now update the text of the card to show these values like this:
function PlayingCard(props) {
return (
<p>The {props.value} of {props.suit}</p>
)
}
To make the code a bit neater, you can use destructuring to extract the individual keys from the props argument in the function signature. Our function would then become:
function PlayingCard({suit, value}) {
return (
<p>The {value} of {suit}</p>
)
}
We restructure the props argument with {suit, value}, and the function code only needs to specify suit or value to use the props now.
Adding State to the component
Now we have the information required to draw the face of the card. We also need a way of determining whether the card is currently face-up or face-down. You can store this information in the state of a React component using hooks.
We will add the useState hook and create a local boolean variable called isFaceUp. If isFaceUp is true, then the suit and value of the card can be read. If it is false, we hide the values and show the back of the card.
import { useState } from "react";
function PlayingCard({suit, value}) {
const [isFaceUp, setIsFaceUp] = useState(false);
return (
<p>The {value} of {suit}</p>
)
}
Line 4 in the above image shows the isFaceUp variable being created as state. To change the state of isFaceUp, we can use the second const parameter setIsFaceUp. We have defined the initial value for isFaceUp to be false.
It is important to note that you could also pass isFaceUp as a prop to the PlayingCard component, but there is a use case that will be covered later for why I have used state for isFaceUp.
Using State for conditional rendering
We now update the return statement of our React component only to show the suit and value when the card is facing up by adding a conditional statement that tests the value of isFaceUp.
import { useState } from "react";
function PlayingCard({suit, value}) {
const [isFaceUp, setIsFaceUp] = useState(false);
return (
isFaceUp && <p>The {value} of {suit}</p>
)
}
Line 6 has been updated to use the logical AND short circuit operator to only render the paragraph when isFaceUp is true.
Updating State based on events
Currently, there is no way that the value of isFaceUp can change. Let’s address this by adding a method to flip the card over when touched.
We only have the paragraph text currently in the component, so we should add a box around this to represent the playing card. We’ll implement this as a div with a border for now.
To listen for clicks on the div, we add the onClick attribute like this:
<div onClick={() => setIsFaceUp(!isFaceUp)}
This code will toggle the isFaceUp boolean value each time anywhere on the div is clicked. You can see this in action in the following gif:
Styling The Component
At this point, it will be helpful to look at actual playing to refresh our minds about what we’re trying to build.
The 10 of Diamonds shown here will be a good style card to design. The most important aspects are that the card can be read either side up. The back of the card has a white border with a red background, so we can try to emulate the same on our playing card.
Sizing The Playing Card
Now that the card shows the value and suit and can be flipped to show the reverse side, we can style it to look more like an actual playing card. Let’s set the card size to match the physical card size ratio. A typical card size is 3.5” x 2.5” or a ratio of 7:5. To convert inches to pixels, we can pick a resolution of 96 PPI (Points Per Inch) and multiply each length by the PPI.
In this case we have: 96 x 3.5 = 336 and 96 x 2.5 = 240 leaving us with a card dimension of 240px x 336px
We can update our div to use these dimensions like this:
With the card size sorted, we need to soften the corners now. Typical rounding of playing cards is done at about the 1/8” mark. So applying the PPI vs 1/8”, we get 12px (1/8*96=12). Let’s apply the border-radius property to the div.
border: "2px solid red", borderRadious: "12px"
Placing The Values On The Card
Now that the card is of the correct size and shape, we can start to lay out the design of the card.
Additionally, we need to print the card’s value in two places. The top left and bottom right. The bottom right number is upside down.
Let’s put two H1 heading elements on the card representing the card’s value. We need to rotate one of the H1 elements 180 degrees:
We now have the card with the values printed (the green is just the background to make the card more defined):
Once we have placed the values, we can put the heart pattern onto the card. This will be done in the same way that we have placed the values on the card. The first five will be put on by positioning alone, and the bottom five will be rotated when positioned.
The following code shows how the hearts are placed on the card:
Our React component is coming along now. We are currently taking props for the suit and the card’s value. The suit prop determines the card design. We should have red for Hearts and Diamonds and black for Spades and Clubs. The icon should also change depending on the suit.
The code previously used a hardcoded FaHeart (from the react-icons package) to display the Heart icon. We can handle the conditional logic to display the correct suit in many ways.
In this instance, we can create a new component that takes a suit prop and returns an icon of the correct size. If we were to wrap the above elements in if/else statements, our code could be exceedingly long.
Setting The Colour Of The Card
Before getting to the icon, we must determine if the suit is red or black. We’ll set the state of the card to know the colour using setState and useEffect.
Because the suit is included as a prop, if we determine the colour of the suit from the prop and then render the card in the same React component, we’ll encounter an endless loop.
The best way to think of this is if we are driving the component’s look via props, we need to ensure we only update the look if the prop changes.
Using the useEffect hook alleviates this problem by using the optional second argument. Because this second argument is a dependency list, changing the list executes the useEffect callback.
By adding suit as the dependency, our component won’t continue to rerender unless the suit prop changes.
This is what the useEffect hook looks like for our playing card:
Following on, we create our SuitIcon component, which will return the correct suit icon based on the suit prop.
The idea for the React component is to replace all occurrences of <FaHeart /> with <SuitIcon />. The SuitIcon component determines the required icon for the component.
An example use of the SuitIcon component will look like this:
As you can see, we are passing in suit and suitColor as props to the SuitIcon.
The new component will be straightforward. It will determine the icon to use from react-icons and return the appropriate one based on the suit prop.
Here is the code for SuitIcon:
function SuitIcon({ suit, style }) {
if (suit === "Hearts") {
return <BsFillSuitHeartFill style={style} />;
} else if (suit === "Diamonds") {
return <BsFillSuitDiamondFill style={style} />;
} else if (suit === "Spades") {
return <BsFillSuitSpadeFill style={style} />;
} else if (suit === "Clubs") {
return <BsFillSuitClubFill style={style} />;
} else {
// If no suit is given then we can just put out little joker faces
return <GiCardJoker style={style} />;
}
}
I’ve added logic to handle cases where the suit prop doesn’t match one of the expected playing card suits. Feel free to handle this however you see fit in your applications.
I’ve decided to use the bootstrap icons for the playing cards, so I’ve imported all the BsFillSuit varieties for the four suits. The GiCardJoker is a joker face for the unmatched suit clause.
We can now control the value and style of the card from a parent component. Let’s do this with the following code that will create an Ace of Spades:
<PlayingCard suit="Spades" value="A" />
Styling The Back Of The Card
Here is the back of the card:
We need to add an inside border that contains a pattern.
Let’s create a div inside the card with a margin of 10 pixels. We’ll also consider the 4 pixels of the border from the outside border to centre the interior div.
The code above shows how we can use the state to show the back of the card. I’ve imported an image that I’ll use as the pattern and have then used that image as the background image of our internal div.
The result looks like this:
Now the card is starting to come together (in terms of style) nicely. We will address the outside red border and flatness of the card next.
Styling The Card Thickness
Firstly, let’s remove the red outside border and replace it with a transparent one. Secondly, we can give the card a drop shadow to make the card seem like it has some thickness.
For the box shadow effect, I’ve used three different box shadows to give the effect of multiple light sources hitting the card. Keeping the border transparent will keep everything in line without adjusting margins with the red border removed.
Animating the card flip
Now we get to the fun part – animating the card flip. We’ll use a basic technique to achieve this using mainly CSS. Previously we used the state to determine what side of the card was showing. Using this CSS method to flip the cards means we don’t have to use state but can use transform to rotate the card in and out of view.
Let’s look at the code changes. First, we remove the short circuit test for isFaceUp before the divs for the front and back of the card:
{isFaceUp && <>
Secondly, we remove the state definition for isFaceUp:
const [isFaceUp, setIsFaceUp] = useState(false);
Adding transforms and transitions
This is where we define how the card should flip. Specifically, we need to configure the timing of the flip and the way the card rotates. This is done by utilising three divs. One is the card, and the other two are the faces of the card.
The following code defines the additional styles we are setting on the card div:
The transformStyle property tells the browser to keep the children elements of the card div in the 3d space (as opposed to flat).
The transition property tells the browser what transition property to execute against, in this case, the transform transition. It also defines the duration of the transition and a timing function. So we use the timing function ease to slow down the transition at the end of the transition.
For the font face of the card, we add the backfaceVisibility property with a value of hidden. This property hides the div contents when rotated.
<div style={{ backfaceVisibility: "hidden" }}>
Additionally, the card’s back face has one additional CSS property, transform. By using transform on the back of the card, we make one side of the card invisible when the component loads.
Previously, we used the onClick event to toggle the isFaceUp boolean state variable. We now want to transform the card when the user clicks the card. We create a new function flipCard, to set the transform CSS property to the card.
onClick={flipCard}
Here is the flipCard function:
function flipCard() {
if (myRef.current.style.transform) {
myRef.current.style.transform = "";
} else {
myRef.current.style.transform = "rotateY(180deg)";
}
}
You will notice references to myRef in the above function. This refers to a DOM element in a React component, so you can safely manipulate it. You can learn about refs in the React documentation here
Using the useRef hook
To create the myRef variable, we need to use the useRef hook. We set up the hook in two main steps. Firstly, create the variable like this:
const myRef = useRef(null);The
Secondly, add the ref attribute to the div we want to reference with myRef.
<div
ref={myRef}
We can use standard DOM manipulation techniques to modify the div in ways that React doesn’t allow. In our case, we update the transform style on click.
The Final Product
Before unveiling the working product GIF, let’s review what we’ve done:
Defined the requirements of the card
Created a functional component
Styled the component
Animated the component
What we haven’t done:
used a styling library to clean up the code
created unit tests for the card
handled edge cases for error handling
handled the responsiveness of the card
Here is the final product:
The final product source code is here. Thanks for reading!