This content originally appeared on Level Up Coding - Medium and was authored by Andrew Allison
I began learning JS in 2014 and was introduced to React about a year after that. It seemed bewildering at first, but years of using it have paid off. Whether you are using it in a professional setting, for homework, as part of a coding exercise for an interview, or even a side project, there are some simple shortcuts you can take to make your life easier. Here is a list of 14 time-saving tips that come to mind.
Quality and Coding Style
1. USE A LINTER!
There is a reason it comes included in the CRA set up and it’s the grown-up thing to do. Go here and read up on why I am putting this as my number 1 tip. I use ESLint because it takes my rambling, incoherent, bug-ridden mess and makes it consistent and battle-worthy. Normally when I’m setting up a brand-new repo I refer to this article on Medium by Alon Valadji.
2. Import Essential Rules
Once you have your Linter set up, throw some rules on that bad boy! Airbnb’s .eslintrc config has been high-key the industry standard for as long as I remember. Sonarjs is clutch; jsx-a11y is another great one too. We’ll talk more about that last one later on.
3. Use Prettier
As the name would imply this makes your code look prettier. The biggest improvement it makes is if you are realllly lazy about fixing your ESLint rule violations Prettier will literally rewrite your code for you.
4. Consider Using Typescript
Typescript works well with React and it protects you from your own recklessness. If you are passing around a variable that is meant to be a number and you try assigning a string value it will blow up on you 🤯. Sometimes type coercion can work in your favor, but it’s these kinds of shortcuts that can lead to bugs later down the line.
5. Clean up your Directory Structure
This tip takes a little more discipline. You will find it’s less work to define helper functions, styled components, types, etc. right there next to your component code when you’re in a rush. I’d argue in favor of having separate components, types, styles, and utilities directories:
Performance
6. Avoid Unnecessary Re-Renders
Neglectful parenting runs rampant in React, so show some love to the children... components. React has an intrinsic Higher Order Component called memo. You can use this almost the exact same way we used to call shouldComponentUpdate back when class components were still cool. (Side Note: Functional components are now preferred in most places over Class Components because they are stateless and don’t use lifecycle methods, leaving you with a pure function at the end of the day).
Furthermore, there are 2 useful React hooks called useMemo and useCallback that help us avoid unnecessary re-renders. useMemo caches the result of an expensive calculation while useCallback caches the function itself and returns the same value every time. This is useful when you have something like a click handler that does the same thing every time you click it, no matter what.
7. Use the Virtual DOM Whenever Possible
In case you’re coming from a vanilla JS background, React has an easier way to manipulate the DOM. It’s called the Virtual DOM or the “V DOM” if you’re trying to sound cool in an interview. It’s a lightweight copy of what you have on-screen. It also only updates those elements that need to change. Furthermore, React manipulates the actual DOM using a batch mechanism instead of sending updates for every single change in state.
Take for example the following code:
const videos = ["https://example.com/video1.mp4", "https://example.com/video2.mp4", ..., "https://example.com/video100.mp4"];
const App = () => {
const [selectedVideo, setSelectedVideo] = useState('');
const handleClickPlay = () => {
const videoElement = document.getElementById(selectedVideo);
const currentlyPlayings = document.getElementsByClassName('playing');
Array.from(currentlyPlayings).forEach((cp) => {
cp.classList.remove('selected');
cp.classList.remove('playing');
cp.classList.add('paused');
cp.pause();
});
videoElement.classList.remove('paused');
videoElement.classList.add('selected');
videoElement.classList.add('playing');
videoElement.play();
};
const handleClickPause = () => {
const videoElement = document.getElementById(selectedVideo);
videoElement.classList.add('selected');
videoElement.classList.remove('playing');
videoElement.classList.add('paused');
videoElement.pause();
};
return (
<div>
{videos.map((video, index) => (
<video
id={`${index}`}
key={`${index}`}
onClick={() => setSelectedVideo(`${index}`)}
src={video}
/>
))}
<button onClick={handleClickPlay}>
Play
</button>
<button onClick={handleClickPause}>
Pause
</button>
</div>
);
};
It’s a pain in the ass to understand what’s going on here, but we only want one video to be selected and play at any given time. This means when we go to select a new video, we have to search the entire tree for the videos that are currently playing and pause them all. It’s not a very scalable pattern even with just 100 videos. Now, see how we can accomplish the same thing with a ref:
const videos = ["https://example.com/video1.mp4", "https://example.com/video2.mp4", ..., "https://example.com/video100.mp4"];
const App = () => {
const selected = useRef();
const handleSelectVideo = ({ currentTarget }) => {
if (selected.current) {
selected.current.classList.remove('playing');
}
selected.current = currentTarget;
};
const handleClickPlay = (e) => {
selected.current.play();
selected.current.classList.remove('paused');
selected.current.classList.add('playing');
};
const handleClickPause = (e) => {
selected.current.pause();
selected.current.classList.remove('playing');
selected.current.classList.add('paused');
};
return (
<div>
{videos.map((video, index) => (
<video
id={`${index}`}
key={`${index}`}
onClick={handleSelectVideo}
src={video}
/>
))}
<button onClick={handleClickPlay}>
Play
</button>
<button onClick={handleClickPause}>
Pause
</button>
</div>
);
};
It’s not that much quicker when simply fetching one element via getElementById and changing it. The competitive advantage comes when dealing with updates to complex subtrees. This is obviously a simple illustration, but when it comes to heavy-duty front end optimization refs will outperform direct DOM manipulation every time.
8. Combine and Reduce API Calls
This tip is not React-specific and the message is mainly “don’t use GraphQL like REST”. Take the following code for example:
import React, { useEffect, useState } from 'react';
const App = () => {
const [name, setName] = useState('');
const [numFollowers, setNumFollowers] = useState(0);
const [error, setError] = useState(undefined);
useEffect(() => {
/**
* query GetUser {
* getUser {
* id
* name
* }
* }
*/
getUser().then(({ name }) => setName).catch(setError);
/**
* query GetNumFollowers($userid: ID!) {
* getNumFollowers(userId: $userid)
* }
*/
getNumFollowers().then(setNumFollowers).catch(setError);
});
return (
<>
<p>Hi my name is {name}</p>
<p>I have {numFollowers} followers</p>
</>
);
};
The more network requests you have the slower it gets, so why not use the competitive advantages of GraphQL?
import React, { useEffect, useState } from "react";
const App = () => {
const [name, setName] = useState("");
const [numFollowers, setNumFollowers] = useState(0);
const [error, setError] = useState(undefined);
useEffect(() => {
/**
* query GetUser {
* getUser {
* name
* followers
* }
* }
*/
getUser()
.then(({ name, followers }) => {
setName(name);
setNumFollowers(followers.length);
})
.catch(setError);
});
return error ? <Alert /> : (
<>
<p>Hi my name is {name}</p>
<p>I have {numFollowers} followers</p>
</>
);
};
You can also reduce the number of network calls by saving data fetched from an API in state at the Parent component-level and sharing it either via props or the React Context API.
9. Leverage Browser Storage
Browser storage is no longer something that you have to remember to delete after a shameful act. In fact, it can make your life easier and the user experience better in many ways! A lot of 3rd party libraries commonly used with React have wrappers around browser storage or use it under the hood. However, it’s time you get to know it better.localStorage can be used to cache things to persist across closing and reopening the browser. An example of localStorage data would be a user’s search history or page bookmark. sessionStorage can be used for ephemeral, short-lived data. An example of sessionStorage data would be a an OAuth token for making API calls. indexedDB can be used for background web worker data. An example of indexedDB data would be pending changes made in an app while offline that can be executed once network connectivity is restored. Additionally, using web workers for CPU intensive tasks will boost your React app’s performance because they will run on a separate thread and won’t slow down processes running on the main thread.
10. Virtualize Large Arrays
Chances are if you are loading an extremely large array into memory you’re going to want to show the items on screen (i.e. so your users can mindlessly scroll like zombies). Rendering everything into the DOM at once will 1) take forever and 2) be laggy once it does load. Take a look at react-window and react-virtualized which provide components for virtualizing large arrays.
11. Code Splitting
Not as hard as doing the splits! Dynamic and Lazy loading is the name of the game here and the official React documentation shows you how to do it fairly easily.
User Experience
12. Add an Error Boundary
This will catch any errors your app can throw. That way your end users don’t get that red screen when your app inevitably crashes. For plain JS copy it right out of the React documentation. For Typescript a quick Google search will turn up a gist you can copy as well. Be sure to invoice your customer $5 for a Googling fee.
13. Standardize and Reuse Your Common Components
Web pages all use standard components so be sure they all look the same. The usual suspects are Buttons, Inputs, and Links. But there is something to be said for standardizing Modals, Alerts, and Spinners as well. If you have the time coming up with a component library is a worthwhile endeavor.
Writing a shared React component library with storybook
14. Internationalize (i18n) and Accessibil-ize (a11y)
Don’t fall victim to an epic translation fail. Winning over a global audience like BTS can happen for your React side project too! react-i18next is a really cool project that actually sources translations dynamically using a backend server called locize. Save yourself a boat load of time and money with this library.
Get your react.js application translated with style…
As I mentioned previously, eslint-plugin-jsx-a11y can help keep you in check when writing JSX. According to the github README:
This plugin does a static evaluation of the JSX to spot accessibility issues in React apps. Because it only catches errors in static code, use it in combination with @axe-core/react to test the accessibility of the rendered DOM. Consider these tools just as one step of a larger a11y testing process and always test your apps with assistive technology.
Here they mention axe-core, developed by Deque for a variety of languages including JS.
axe-core-npm/packages/react at develop · dequelabs/axe-core-npm
Additionally, you should probably get in the habit of writing correct semantic HTML regardless if you are using React or not. The official React documentation has more tips on how to improve the accessibility of your site:
TL;DR you can use libraries for this
Conclusion
In addition to the tips mentioned here you can always implement best practices that are not specific to React such as using a CDN, caching at the API and DB level, importing UX designer wireframes, tree shaking, cutting down on the total bundle size, etc. the list goes on forever but you get the point.
If you like my style of corny writing please follow. I publish ~1x a month and I love to network. Thanks
14 Tips for Effortlessly Improving your Weak Ass React Code was originally published in Level Up Coding on Medium, where people are continuing the conversation by highlighting and responding to this story.
This content originally appeared on Level Up Coding - Medium and was authored by Andrew Allison
Andrew Allison | Sciencx (2022-06-22T15:21:31+00:00) 14 Tips for Effortlessly Improving your Weak Ass React Code. Retrieved from https://www.scien.cx/2022/06/22/14-tips-for-effortlessly-improving-your-weak-ass-react-code/
Please log in to upload a file.
There are no updates yet.
Click the Upload button above to add an update.