π» React Component Tips
In this post I share some tips for how you can refactor your react components to be readable and declarative π£
Table of Contents
- Remove extra divs
- Remove unnecessary closing tags
- Use template literals instead of concatenation
- Destructure props
- Set defaults while destructuring
- Avoid verbose nullchecks
- Never use βvarβ
- Use βconstβ instead of βletβ
- Use the ternary operator
#1. Remove extra divs
Use <>
(react fragment shorthand) if you just need an invisible container
β Instead of this:
const Component = () => {
return (
<div>
<span>One</span>
<span>Two</span>
<span>Three</span>
</div>
);
};
βοΈ Do this:
const Component = () => {
return (
<>
<span>One</span>
<span>Two</span>
<span>Three</span>
</>
);
};
#2. Remove unnecessary closing tags
If an element does not have any children, a named closing tag is not required
Just close the element with />
instead
β Instead of this:
const Component = () => {
return <Child foo={bar}></Child>;
};
βοΈ Do this:
const Component = () => {
return <Child foo={bar} />;
};
#3. Use template literals instead of concatenation
Avoid concatenating strings by using template literals instead
β Instead of this:
const Component = ({ classes }) => {
return <div className={"bg-white " + classes} />;
};
βοΈ Do this:
const Component = ({ classes }) => {
return <div className={`bg-white ${classes}`} />;
};
#4. Destructure props
Destructure your props to eliminate repeating βprops.
β throughout the component
β Instead of this:
const Component = (props) => {
return (
<div>
<h1>{props.title}</h1>
<span>{props.date}</span>
<p>{props.description}</p>
</div>
);
};
βοΈ Do this:
const Component = ({ title, date, description }) => {
return (
<div>
<h1>{title}</h1>
<span>{date}</span>
<p>{description}</p>
</div>
);
};
You can destructure any variable within the function as well
Useful if you need to pass the entire props variable to a child
const Component = (props) => {
const { title, date, description } = props;
return (
<div>
<h1>{title}</h1>
<span>{date}</span>
<p>{description}</p>
<Child {...props} />
<OtherChild foobar={props} />
</div>
);
};
#5. Set defaults while destructuring
Avoid using imperative logic to redefine properties
Instead you can set a default value while destructuring
β Instead of this:
const Component = ({ propertyA }) => {
let _propertyA = "default";
if (propertyA !== undefined) {
_propertyA = propertyA;
}
return <>{propertyA}</>; // returns "default" if propertyA is undefined
};
βοΈ Do this:
const Component = ({ propertyA = "default" }) => {
return <>{propertyA}</>; // returns "default" if propertyA is undefined
};
Note that null
, false
, and ""
(empty string) would all be valid inputs for propertyA
and would bypass the default. See Avoid verbose nullchecks for how to solve this
#6. Avoid verbose nullchecks
undefined
and null
are considered βfalsy
β by JavaScript.
You can check that a property is not falsy using the logical AND operator (&&
)
β Instead of this:
const Component = ({ propertyA }) => {
let propertyAIsValid = false;
if (propertyA !== undefined && propertyA !== null && propertyA !== "") {
propertyAIsValid = true;
}
return propertyAIsValid ? <>Yep it's valid!</> : <>Invalid propertyA</>;
};
βοΈ Do this:
const Component = ({ propertyA }) => {
return propertyA && propertyA !== "" ? (
<>Yep it's valid!</>
) : (
<>Invalid propertyA</>
);
};
#7. Never use βvarβ
From stackoverflow:
var is on ES6 for legacy reasons. In theory, the let statement is better since it behaves more predictably on block scopes, but it wonβt work with more outdated interpreters. So, if youβre coding with only ES6 in mind, go for let.
#8. Use βconstβ instead of βletβ
βconst
β defines a constant
that canβt be changed later
βlet
β defines a variable
that can be changed later
If you find yourself needing to use βlet
β, you might be trying to create imperative logic.
Try to rethink the problem and define once using βconst
β
β Instead of this:
const Component = ({ size }) => {
let className = "bg-white accent-bottom-primary";
if (size === "large") {
className = className + " large";
} else if (size === "small") {
className = className + " small";
}
return <div className={className} />;
};
βοΈ Do this:
const Component = ({ size }) => {
const className = `bg-white accent-bottom-primary${size ? ` ${size}` : ""}`;
return <div className={className} />;
};
#9. Use the ternary operator
The ternary operator shortens your if statement logic and makes your code read a bit like a spoken question
condition ?
evaluates if true :
evaluates if false
βAre we loading ?
yes, so show < Loading /> :
no, so show < Done />β
β Instead of this:
const Component = ({ loading }) => {
if (loading) {
return <Loading />;
} else {
return <Done />;
}
};
βοΈ Do this:
const Component = ({ loading }) => {
return loading ? <Loading /> : <Done />;
};
You can nest multiple ternary operators for more complex conditions
const Component = ({ loading, data, error }) => {
const empty = !data || data.length === 0;
return loading ? (
<div>Loading</div>
) : empty ? (
<div>Data is empty</div>
) : error ? (
<div>There was an error</div>
) : (
<div>Your data is: {data}</div>
);
};
Thanks for reading π