8 Proven Techniques to Write Cleaner React Code
This article presents eight practical ways to write cleaner, more readable React code, covering conditional rendering, boolean and string props, event handlers, component‑as‑prop patterns, undefined props, state updates, and general JavaScript clean‑code practices, each illustrated with bad and good examples.
This article is translated from "React Clean Code - Simple ways to write better and cleaner code".
Clean code is not just code that runs; it should be easy to read, simple to understand, and well‑structured. In this article we introduce eight methods for writing cleaner React code.
1. Conditional rendering with a single condition
When the condition is
truerender some content, and render nothing when it is
false. Use the
&&operator instead of the ternary operator.
Bad example:
import React, { useState } from 'react'
export const ConditionalRenderingWhenTrueBad = () => {
const [showConditionalText, setShowConditionalText] = useState(false)
const handleClick = () =>
setShowConditionalText(showConditionalText => !showConditionalText)
return (
<div>
<button onClick={handleClick}>Toggle the text</button>
{showConditionalText ? <p>The condition must be true!</p> : null}
</div>
)
}Good example:
import React, { useState } from 'react'
export const ConditionalRenderingWhenTrueGood = () => {
const [showConditionalText, setShowConditionalText] = useState(false)
const handleClick = () =>
setShowConditionalText(showConditionalText => !showConditionalText)
return (
<div>
<button onClick={handleClick}>Toggle the text</button>
{showConditionalText && <p>The condition must be true!</p>}
</div>
)
}2. Conditional rendering with two conditions
Use the ternary operator when you need to render one piece of content for
trueand another for
false.
Bad example:
import React, { useState } from 'react'
export const ConditionalRenderingBad = () => {
const [showConditionOneText, setShowConditionOneText] = useState(false)
const handleClick = () =>
setShowConditionOneText(showConditionOneText => !showConditionOneText)
return (
<div>
<button onClick={handleClick}>Toggle the text</button>
{showConditionOneText && <p>The condition must be true!</p>}
{!showConditionOneText && <p>The condition must be false!</p>}
</div>
)
}Good example:
import React, { useState } from 'react'
export const ConditionalRenderingGood = () => {
const [showConditionOneText, setShowConditionOneText] = useState(false)
const handleClick = () =>
setShowConditionOneText(showConditionOneText => !showConditionOneText)
return (
<div>
<button onClick={handleClick}>Toggle the text</button>
{showConditionOneText ? (
<p>The condition must be true!</p>
) : (
<p>The condition must be false!</p>
)}
</div>
)
}3. Boolean props
When a prop is
true, you can omit the explicit value and just write the prop name.
Bad example:
import React from 'react'
const HungryMessage = ({ isHungry }) => (
<span>{isHungry ? 'I am hungry' : 'I am full'}</span>
)
export const BooleanPropBad = () => (
<div>
<span><b>This person is hungry:</b></span>
<HungryMessage isHungry={true} />
<br />
<span><b>This person is full:</b></span>
<HungryMessage isHungry={false} />
</div>
)Good example:
import React from 'react'
const HungryMessage = ({ isHungry }) => (
<span>{isHungry ? 'I am hungry' : 'I am full'}</span>
)
export const BooleanPropGood = () => (
<div>
<span><b>This person is hungry:</b></span>
<HungryMessage isHungry />
<br />
<span><b>This person is full:</b></span>
<HungryMessage />
</div>
)4. String props
Assign string values with double quotes; do not use braces or template literals.
Bad example:
import React from 'react'
const Greeting = ({ personName }) => <p>Hi, {personName}!</p>
export const StringPropValuesBad = () => (
<div>
<Greeting personName={"John"} />
<Greeting personName={'Matt'} />
<Greeting personName={`Paul`} />
</div>
)Good example:
import React from 'react'
const Greeting = ({ personName }) => <p>Hi, {personName}!</p>
export const StringPropValuesGood = () => (
<div>
<Greeting personName="John" />
<Greeting personName="Matt" />
<Greeting personName="Paul" />
</div>
)5. Event handler functions
If a handler only needs the event object, pass the function directly instead of wrapping it in an anonymous arrow function.
Bad example:
import React, { useState } from 'react'
export const UnnecessaryAnonymousFunctionsBad = () => {
const [inputValue, setInputValue] = useState('')
const handleChange = e => {
setInputValue(e.target.value)
}
return (
<>
<label htmlFor="name">Name:</label>
<input id="name" value={inputValue} onChange={e => handleChange(e)} />
</>
)
}Good example:
import React, { useState } from 'react'
export const UnnecessaryAnonymousFunctionsGood = () => {
const [inputValue, setInputValue] = useState('')
const handleChange = e => {
setInputValue(e.target.value)
}
return (
<>
<label htmlFor="name">Name:</label>
<input id="name" value={inputValue} onChange={handleChange} />
</>
)
}6. Passing components as props
If a component prop does not need additional props, pass the component directly without wrapping it in a function.
Bad example:
import React from 'react'
const CircleIcon = () => (
<svg height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
)
const ComponentThatAcceptsAnIcon = ({ IconComponent }) => (
<div>
<p>Below is the icon component prop I was given:</p>
<IconComponent />
</div>
)
export const UnnecessaryAnonymousFunctionComponentsBad = () => (
<ComponentThatAcceptsAnIcon IconComponent={() => <CircleIcon />} />
)Good example:
import React from 'react'
const CircleIcon = () => (
<svg height="100" width="100">
<circle cx="50" cy="50" r="40" stroke="black" stroke-width="3" fill="red" />
</svg>
)
const ComponentThatAcceptsAnIcon = ({ IconComponent }) => (
<div>
<p>Below is the icon component prop I was given:</p>
<IconComponent />
</div>
)
export const UnnecessaryAnonymousFunctionComponentsGood = () => (
<ComponentThatAcceptsAnIcon IconComponent={CircleIcon} />
)7. Undefined props
Undefined props are automatically ignored; if a prop is allowed you do not need extra checks.
Bad example:
import React from 'react'
const ButtonOne = ({ handleClick }) => (
<button onClick={handleClick || undefined}>Click me</button>
)
const ButtonTwo = ({ handleClick }) => {
const noop = () => {}
return <button onClick={handleClick || noop}>Click me</button>
}
export const UndefinedPropsBad = () => (
<div>
<ButtonOne />
<ButtonOne handleClick={() => alert('Clicked!')} />
<ButtonTwo />
<ButtonTwo handleClick={() => alert('Clicked!')} />
</div>
)Good example:
import React from 'react'
const ButtonOne = ({ handleClick }) => (
<button onClick={handleClick}>Click me</button>
)
export const UndefinedPropsGood = () => (
<div>
<ButtonOne />
<ButtonOne handleClick={() => alert('Clicked!')} />
</div>
)8. State updates that depend on previous state
When the new state depends on the previous one, use the functional form of the state setter to avoid stale closures.
Bad example:
import React, { useState } from 'react'
export const PreviousStateBad = () => {
const [isDisabled, setIsDisabled] = useState(false)
const toggleButton = () => setIsDisabled(!isDisabled)
const toggleButton2Times = () => {
for (let i = 0; i < 2; i++) {
toggleButton()
}
}
return (
<div>
<button disabled={isDisabled}>I{'m {isDisabled ? 'disabled' : 'enabled'}</button>
<button onClick={toggleButton}>Toggle button state</button>
<button onClick={toggleButton2Times}>Toggle button state 2 times</button>
</div>
)
}Good example:
import React, { useState } from 'react'
export const PreviousStateGood = () => {
const [isDisabled, setIsDisabled] = useState(false)
const toggleButton = () => setIsDisabled(isDisabled => !isDisabled)
const toggleButton2Times = () => {
for (let i = 0; i < 2; i++) {
toggleButton()
}
}
return (
<div>
<button disabled={isDisabled}>I{'m {isDisabled ? 'disabled' : 'enabled'}</button>
<button onClick={toggleButton}>Toggle button state</button>
<button onClick={toggleButton2Times}>Toggle button state 2 times</button>
</div>
)
}Other practices
These practices are not React‑specific but are good JavaScript (or any language) clean‑code habits:
Extract complex logic into well‑named functions.
Replace magic numbers with constants.
Use clearly named variables.
Happy coding!
KooFE Frontend Team
Follow the latest frontend updates
How this landed with the community
Was this worth your time?
0 Comments
Thoughtful readers leave field notes, pushback, and hard-won operational detail here.