React’s value add for frontend developers is that it makes single page web app development much easier by combining the well understood syntax of HTML with the scripting capabilities of JavaScript in an intuitive and convenient way.
One of React’s most important features that is easy for new developers to overlook is component reusability. We need to be building React components that are designed to be reused throughout the UI.
I get it though, it can be hard to see how a component can be reused. I hope to be able to pass on some tips that I’ve learned during my journey into React to help keep components reusable.
Start with the planning stage
In the last post in the series, I broke down a series of wireframes into a component hierarchy. Detailed planning is the first step to identifying reusable components.
When looking at a mockup or a wireframe, it’s critical to identify parts of the UI which are identical to other parts of the UI or are extremely similar but with minor variations.
Aristotle and UI
The Greek philosopher Aristotle formalized thought regarding an object’s essence. According to Aristotle, an object’s essence is the set of characteristics that make the object what it is and without which it would not be what it is.
For example, we could say that the essence of a button is its clickability. All buttons are clickable and perform some action when clicked. Similarly, if a part of a UI is never clickable, then we can say that it is not a button.
In contrast to an object’s essence, Aristotle held that objects also have “accidental” characteristics. Basically what Aristotle meant by the term “accidental” is “not essential”. That is, an accidental characteristic is something which can be removed from an object without making the object something other than what it is.
In our example, a button’s color, shape, or text would all be accidental characteristics because they can all be changed without making the button not a button. A red button is still a button.
In Aristotle’s thought, an “accidental” characteristic is not one which occurs by chance, but rather a characteristic which can be altered without changing the object into a different kind of object.
How does all this relate to reusability ♻️?
When identifying reusable components, first look for all the parts of the UI which share essential characteristics. Identify UI elements which are accidental characteristics of the components to which they belong, so that you can see all the features that it shares in common with similar components.
Reusable components share the same set of essential characteristics in every part of the UI, even though some of their accidental characteristics might change between parts of the UI.
Building Reusable components
If you haven’t already, create a new react app for our forum project.
npx create-react-app
When it’s finished, navigate to the new project and install missing dependencies:
yarn add @mdi/js @mdi/react bulma rbx \
react-router react-router-dom \
graphql-request redux react-redux \
immer easy-redux-reducers
Here’s a brief explanation of the dependencies
- Bulma, rbx: npm packages to use the bulma framework with react
-
@mdi/js
,@mdi/react
: packages to use the material design icon font with react -
react-router
,react-router-dom
: allows us to have multiple pages in one react app. -
graphql-request
: allows us to easily query our GraphQL backend. -
redux,
react-redux
: helps us manage complex application state - immer: allows us to maintain immutability but also to modify state objects directly.
- easy-redux-reducers: a tiny package to eliminate the need for writing switch statements in redux reducers.
Once those are finished installing, we’re ready to begin building reusable components
Delete unnecessary files
Remove the files index.css
, app.css
, logo.svg
, favicon.ico
and all the references to those files. We won’t need them and they’ll just get in the way.
Creating our first reusable component
Let’s tackle the most reused component in our component hierarchy: Field
. If you look back at the last post, you’ll see that this field is probably the most reused component in the whole hierarchy.
For clarity, I’m calling Field
FormField
in the actual code to reduce ambiguity since there is a field
component in Bulma.
Here’s my code for FormField
:
// src/components/FormField.js
import React from 'react';
import {Field, Label, Control, Input} from 'rbx';
const FormField = props => {
return <Field>
<Label>{props.name}:</Label>
<Control>
<Input
type="text"
placeholder={props.name}
value={props.value}
onChange={props.onChange}
/>
</Control>
</Field>
};
export default FormField;
The Field
, Label
, Control
, and Input
components are all components from rbx
required to use Bulma styles and make sure that they stay consistent.
Notice that I have not actually passed any values (other than the “text” property) to any of the components. This is key to keeping a component reusable. We need to make sure it behaves predictably in whatever context we use it.
FormField
does not maintain any state, but rather expects an onChange
prop so that it’s parent component can keep track of state management. Since FormField
is a functional component, getting the value of the Input
component would have been challenging.
The TopicTitle
component
Let’s look at another example. Here’s my code for the TopicTitle
component:
import React from 'react';
import { withRouter } from 'react-router-dom';
import { Box, Title } from 'rbx';
const TopicTitle = props => {
return <Box onClick={()=> props.history.push({pathname: props.to})}>
<Title>{ props.text }</Title>
</Box>
}
export default withRouter(TopicTitle);
This component displays the title of a topic and also acts as a link to the topic itself. Again, by using props, I can make this component highly reusable with minimal effort. I wrapped the whole component in react-router
’s withRouter()
function to enable it to properly integrate with the browser’s history API.
Go build some reusable♻️ components
I hope I have been able to give you some tips regarding how to make React components reusable. As always, feel free to ask me questions in the comments.
The code for this part of the series is available on GitHub
speratus / miniforum-frontend
The React frontend for the Miniforum repo
This project was bootstrapped with Create React App.
Available Scripts
In the project directory, you can run:
yarn start
Runs the app in the development mode.
Open http://localhost:3000 to view it in the browser.
The page will reload if you make edits.
You will also see any lint errors in the console.
yarn test
Launches the test runner in the interactive watch mode.
See the section about running tests for more information.
yarn build
Builds the app for production to the build
folder.
It correctly bundles React in production mode and optimizes the build for the best performance.
The build is minified and the filenames include the hashes.
Your app is ready to be deployed!
See the section about deployment for more information.
yarn eject
Note: this is a one-way operation. Once you eject
, you can’t go back!
If you aren’t satisfied with the build tool and configuration…
Top comments (0)