DEV Community

Cover image for React Clean Code - Simple ways to write better and cleaner code
Tyler Hawkins
Tyler Hawkins

Posted on • Edited on • Originally published at betterprogramming.pub

React Clean Code - Simple ways to write better and cleaner code

Clean code is more than just working code. Clean code is easy to read, simple to understand, and neatly organized. In this article we’ll look at eight ways we can write cleaner React code.

In going through these suggestions, it’s important to remember that that’s exactly what these are: suggestions. If you disagree with any of them, that’s completely fine. However, these are practices that I’ve found helpful in writing my own React code. Let’s dive in!


1. Conditional rendering only for one condition

If you need to conditionally render something when a condition is true and not render anything when a condition is false, don’t use a ternary operator. Use the && operator instead.

Bad example:

Good example:


2. Conditional rendering on either condition

If you need to conditionally render one thing when a condition is true and render a different thing when the condition is false, use a ternary operator.

Bad example:

Good example:


3. Boolean props

A truthy prop can be provided to a component with just the prop name without a value like this: myTruthyProp. Writing it like myTruthyProp={true} is unnecessary.

Bad example:

Good example:


4. String props

A string prop value can be provided in double quotes without the use of curly braces or backticks.

Bad example:

Good example:


5. Event handler functions

If an event handler only takes a single argument for the Event object, you can just provide the function as the event handler like this: onChange={handleChange}. You don't need to wrap the function in an anonymous function like this: onChange={e => handleChange(e)}.

Bad example:

Good example:


6. Passing components as props

When passing a component as a prop to another component, you don’t need to wrap this passed component in a function if the component does not accept any props.

Bad example:

Good example:


7. Undefined props

Undefined props are excluded, so don’t worry about providing an undefined fallback if it's ok for the prop to be undefined.

Bad example:

Good example:


8. Setting state that relies on the previous state

Always set state as a function of the previous state if the new state relies on the previous state. React state updates can be batched, and not writing your updates this way can lead to unexpected results.

Bad example:

Good example:


Honorable Mention

The following practices are not React-specific but rather are good practices for writing clean code in JavaScript (and any programming language, for that matter).

  • Extract complex logic into clearly-named functions
  • Extract magic numbers into constants
  • Use clearly named variables

Happy coding!

Latest comments (68)

Collapse
 
p10 profile image
p10

clean code !== pretty code
This article is about pretty code

Collapse
 
garystorey profile image
Gary Storey

For those looking for a short simple solution to conditional rendering:

const Show = ({when=false, children}) = when ? <>{children}</> : null
Enter fullscreen mode Exit fullscreen mode

and usage in your component:

const [show, setShow] = useState(false);
<Show when={show}>
Hello!
</Show>
Enter fullscreen mode Exit fullscreen mode

It uses a Fragment as a wrapper in case the user does not have a single parent element in children

Collapse
 
lpyexplore profile image
Lpyexplore

Hello, I am a front-end enthusiast and I am from China. I just read your article and think it is very good. So I want to translate your article into Chinese and publish it on a Chinese blog site. I have nearly 20,000 fan readers. I want to share your article with more people. I want to ask for your information. Opinion, can I do this? Hope to get your reply!

Collapse
 
thawkin3 profile image
Tyler Hawkins

Sure thing! As long as you include the link to this original post, that's fine with me. Can you comment back here with your translated blog post URL once you publish it?

Collapse
 
lpyexplore profile image
Lpyexplore

Of course! Thank you for agreeing to translate this article. After I translate and publish the article, I will attach a URL below this comment. And I will attach a link to the original text in the article

Collapse
 
lpyexplore profile image
Lpyexplore

Hello, I am a front-end enthusiast and I am from China. I just read your article and think it is very good. So I want to translate your article into Chinese and publish it on a Chinese blog site. I have nearly 20,000 fan readers. I want to share your article with more people. I want to ask for your information. Opinion, can I do this? Hope to get your reply

Collapse
 
mavortius profile image
Marcelo Martins

Good article, but those are tips for beginers anyway.

Collapse
 
tomaszs2 profile image
Tom Smykowski

Id love to see these rules for Assistan extension for Vscode marketplace.visualstudio.com/items...

Collapse
 
vedovelli profile image
Fábio Vedovelli

Thanks for the article. I see several people advocating against short-circuiting with &&, as you stated in your first example. By using short-circuit you run into the risk of ending up with a rendered the number 0 (zero) instead of your component.

Collapse
 
thawkin3 profile image
Tyler Hawkins

Thanks Fábio! That's true, to an extent. There was some good discussion in another thread and a reference to a Kent Dodds blog post where he advocates against using &&.

I do think it's important to note that the issue isn't necessarily with short-circuiting and the && operator, but rather from misusing it or misunderstanding how short-circuiting works.

For example, you can avoid rendering "0" in your UI from writing myArray.length && <MyComponent /> by instead using any of the following:

  • myArray.length > 0
  • !!(myArray.length)
  • Boolean(myArray.length)

But it's true that using the ternary makes it so you don't have to think about this and can just write: myArray.length ? <MyComponent /> : null.

So it really comes down to personal preference and the tradeoff of whether you like having the extra : null in your code or if you can remember to be careful in how you evaluate the length of an array in your conditional.

Collapse
 
lequanghuylc profile image
Lê Quang Huy • Edited

Thanks for writing this article. In my opinion, clean code also means it's easier to upgrade it to be the more complex code, it'll be clean when you have your reasons ( and be sure other maintainers know your reasons via docs).

1 & 2 Conditional rendering

in order to avoid weird crash on some Android devices (assuming that we all try React Native someday), this is what I use all the time

<>
 {Boolean(showConditionalText) && <ConditionalTextComponent />}
</>
Enter fullscreen mode Exit fullscreen mode

This will prevent someone to assign a text variable to showConditionalText, it's fine on the web because we can render text as direct child.

4 String props

if you use curly braces, it'll be more convenient to convert it to variable later, and you will convert alot

// from
<Greeting personName={"John"} />
// to
<Greeting personName={userInfo.name} />
Enter fullscreen mode Exit fullscreen mode

It's more like Class Component vs Functional Component in the past, everyone wants to write a functional component in the beginning, but ends up converting it to class component.

8

Just want to share another way to deal with states, it does not relate much to your example. It's when you have dozen of useState variables, and the docs recommend useCallback, so the function always have most updated values. If keeping track of when to use useCallback or normal function, keeping track of the values cost you too much time, you can use a mutable variable and you can access anytime without useCallback

const [entityAData, setEntityAData] = useState(initialValueA);
const [entityBData, setEntityBData] = useState(initialValueB);

const entityADataRef = useRef(initialValueA);
const entityBDataRef = useRef(initialValueB);

useEffect(() => {
  entityADataRef.current = entityAData;
}, [entityAData]);
useEffect(() => {
  entityBDataRef.current = entityBData;
}, [entityBData]);

// entityADataRef.current and entityBDataRef.current will always be updated. free to use it as ready only variable, without callback

// we can write a custom hook to keep it short and avoid repeating code
Enter fullscreen mode Exit fullscreen mode
Collapse
 
mrchedda profile image
mr chedda

Boolean(value) === !!value. The latter is just more concise

Collapse
 
lequanghuylc profile image
Lê Quang Huy

True. But the article was saying about showConditionText, not !!showConditionText. Without the way to force the variable to be boolean, it will cause problem if the variable somehow is assigned to text or object.

And Boolean() is more convenient when doing a complex comparison (more than one)

Thread Thread
 
mrchedda profile image
mr chedda

I’m not sure you understand. I’m commenting on your comment. You suggested to use Boolean(showConditionText) instead of the raw variable: showConditionText. I’m only pointing out that !!showConditionText is a more concise syntax of Boolean(showConditionText). Pre-pending any variable with !! Is implicitly coercing it to a Boolean. Further more Boolean() only takes one argument so I’m not sure how it handles more “complex” comparisons?

Thread Thread
 
lequanghuylc profile image
Lê Quang Huy

Complex means more than one variable. Often goes with && or ||

For example Boolean(a && b && c). In order to write !!(a && b && c), if you start with !!a you need to add “(” before a and add b c after a and I dont like that. I just want to put the cursor inside the “()” and write new variables.

If you understand my comment, you’ll know I talk about the possibility of expanding the code from simple to be more complex logic.

Thread Thread
 
mrchedda profile image
mr chedda • Edited

That's not what your suggestion was but in that case it would simply be

( (!!a && !!b && !!c) || !!d ) && <Component />
Enter fullscreen mode Exit fullscreen mode

Your suggestion above would result in

( (Boolean(a) && Boolean(b) && Boolean(c)) || Boolean(d) ) && <Component />
Enter fullscreen mode Exit fullscreen mode

which is not efficient nor concise

Thread Thread
 
lequanghuylc profile image
Lê Quang Huy

@mr chedda
The first one is too many !!
The second one, is funny, because I literally gave my example above. How could you see my example and come up with that?
If you mean “result in” is how the computer sees it, all of your examples, my examples and Ryan’s examples, are the same to the computer.
And if you mean “result in” is the way that I actually write it. I will write it again and hope you can get it

Boolean((a && b && c) || d) &&

Thread Thread
 
mrchedda profile image
mr chedda

Lê.... Maybe it's because English is NOT your first language but the two statements I wrote are programmatically equivalent but your syntax is written in a more beginner way.

You likely WILL NOT see this in a production code base written by senior developers.

( Boolean(a) && Boolean(b) && Boolean(c)) || Boolean(d) ) && <Component />
Enter fullscreen mode Exit fullscreen mode

You likely WILL see this syntax in a production code base written by senior developers:

( ( !!a && !!b && !!c ) || !!d ) && <Component />
Enter fullscreen mode Exit fullscreen mode

I don't know how I can make it any clearer.... the two statements are saying THE EXACT SAME THING... the difference is your suggestion using Boolean() would likely be written by a beginner programmer.

Thread Thread
 
lequanghuylc profile image
Lê Quang Huy

So your comment is about:

  1. You wrote an example with multiple “Boolean()” and assume I came up with that, when in two of my examples, multiple variables inside just one “Boolean()”

  2. repeated what I said about “the exact same thing”, yes the computer would understand them the same way, we’re talking about Coding style, the convenient of upgrading the code to more complex logic.

  3. Didnt have any reply to my “too many !!”. Made an execuse the seniors are using it, production code.. bla bla

  4. Personal attack about English not my native language, beginner level

Keep it up, you’re doing real great. Dont worry too much, I’ve been through many years of js development, your comments and your capital letters wont make me a beginner.

Collapse
 
gene profile image
Gene
  • Lint your code. It helps make code cleaner as well.

Thanks for this!

Collapse
 
thawkin3 profile image
Tyler Hawkins

You're welcome! Absolutely, linters and auto-formatters are a must. Every project I work on includes ESLint and Prettier, and if it's not already there in a repo I inherit, that's one of the first things I add!

Collapse
 
angeloanolin profile image
Angelo Anolin

Really liked the suggestions with regards to the conditional rendering. Slowly refactoring some codes I have written to follow that. Great article!

Collapse
 
thawkin3 profile image
Tyler Hawkins

Thank you!

Some comments may only be visible to logged-in visitors. Sign in to view all comments.