Code guidelines to use in this project
- Use interfaces to define component props or method arguments.
- Use types to define object/data shapes.
❌ Don't
// Example 1:
type FooProps {
onClick: () => void
}
const Foo = (props: FooProps) => { ... }
// Example 2:
interface Element {
id: string;
children: Array<Element>
}
const getEnabledElements = (elements: Element[]) =>
✅ Do
interface FooProps {
onClick: () => void
}
const Foo = (props: FooProps) => { ... }
// Example 2:
type Element {
id: string;
children: Array<Element>
}
const getEnabledElements = (elements: Array<Element>) => { ... }
- Use
&&
if the left-hand side value isboolean
- Use
ternary operator
if the left-hand side value could resolve to a truthy value
❌ Don't
const showFoo: boolean = shouldRenderFoo();
const bar: Bar[] = [];
// Example 1:
return <>{ showFoo ? <Foo /> : null }</> // `boolean` values don't need a ternary operator
// Example 2:
return <>{ bar.length && <Foo /> }</> // This will display a `zero`
✅ Do
const showFoo: boolean = shouldRenderFoo();
const bar: Bar[] = [];
// Example 1:
// Use `&&` if the left-hand side value is `boolean`
return <>{ showFoo && <Foo /> }</>
// Example 2:
// Use `ternary operator` if the left-hand side value is an Array
return <>{ bar.length ? <Foo /> : null }</> // This prevents a `zero | 0` from being displayed
Preferred explicit if condition over short circuit expression to execute optional
component props.
❌ Don't
onClick && onClick();
✅ Do
if(onClick) onClick();
// 1 Libraries
import cn from 'classnames';
import Image from 'next/image';
import { FaTwitterSquare, FaLinkedin, FaWhatsapp, FaMeetup } from 'react-icons/fa';
// 2 @ Libraries
import { FluidContainer, TopBar } from '@makinox/makinox-ui';
// 3 @ Aliases
import { FluidContainer, TopBar } from '~/components/icon';
// 4 @ Local imports
import headerimage from '../../public/assets/BAQJS.png';
❌ Don't
const foo(callback) {
const isValid = getValidResult();
if(isValid) {
callback();
}
}
✅ Do
const foo(callback) {
const isValid = getValidResult();
if(!isValid) return;
callback();
}
Combine interrelated strings within a single enum value for easy track and reusability.
❌ Don't
const foo(bar: string, callback: () => void) {
if(bar !== "completed") return;
callback();
}
✅ Do
enum Status = {
completed = "completed"
pending = "pending"
}
const foo(bar: Status, callback: () => void) {
if(bar !== Status.completed) return;
callback();
}
Preferred as team consensus to use generic array types over short hand square brackets syntax.
❌ Don’t
type Element = {
id: string;
children: Element[];
}
✅ Do
type Element = {
id: string;
children: Array<Element>;
}
Preferred to turn plain values into variables with a meaningful name.
❌ Don't
setTimeout(() => {
console.log("hello!")
}, 1500)
✅ Do
const DISPLAY_HELLO_TIMEOUT = 1500;
const DEAFULT_MESSAGE = "hello!";
setTimeout(() => {
console.log(DEAFULT_MESSAGE)
}, DISPLAY_HELLO_TIMEOUT)
Preferred to remove commented code blocks which are not going to be used anymore.
❌ Don't
const foo() {
// const getSomeFoo = () => {
// console.log('here you have some foo');
// }
return true;
}
✅ Do
const foo() {
return true;
}
This is recommended for situations where a variable has the same name as an object key, so we can reduce verbosity in the code.
❌ Don't
const study = {
id: id, // This is the scenario we need to prevent
age: pacient.age
}
✅ Do
const study = {
id,
age: pacient.age
}
Preferred to use the () ⇒ void
type for noop functions instead of VoidFunction
❌ Don't
export const foo = (callback: VoidFunction) => {}
✅ Do
export const foo = (callback: () => void) => {}
❌ Don't
export const Navbar = ({ className, onClick }: NavbarProps) => {
const [value, setValue] = useState<string>();
const handleClick = () => {
if (onClick) onClick();
setValue('');
};
const classes = cn(className, 'e-flex e-items-center e-px-4'); // Middle
return (
<nav className={classes} onClick={handleClick}>
{value}
</nav>
);
};
✅ Do
export const Navbar = ({ className, onClick }: NavbarProps) => {
const classes = cn(className, 'e-flex e-items-center e-px-4'); // Top
const [value, setValue] = useState<string>();
const handleClick = () => {
if (onClick) onClick();
setValue('');
};
return (
<nav className={classes} onClick={handleClick}>
{value}
</nav>
);
};
❌ Don't
export const Navbar = ({ className, onClick }: NavbarProps) => {
const navbarClassName = cn(className, 'e-flex e-items-center e-px-4');
const [value, setValue] = useState<string>();
const handleClick = () => {
if (onClick) onClick();
setValue('');
};
return (
<nav className={navbarClassName} onClick={handleClick}>
{value}
</nav>
);
};
✅ Do
export const Navbar = ({ className, onClick }: NavbarProps) => {
const classes = cn(className, 'e-flex e-items-center e-px-4');
const [value, setValue] = useState<string>();
const handleClick = () => {
if (onClick) onClick();
setValue('');
};
return (
<nav className={classes} onClick={handleClick}>
{value}
</nav>
);
};
In order to match the classes
object with the component anatomy, use an object where each key matches with one component’s part.
export const Navbar = ({ ariaLabel, className }: NavbarProps) => {
const classes = {
container: cn(className, 'e-flex e-items-center e-px-4'),
header: cn('e-bg-primary-50'),
body: cn('e-flex e-flex-col'),
footer: cn('e-text-4xl e-text-primary-50'),
};
return (
<nav aria-label={ariaLabel} className={classes.container}>
{/* HEADER */}
<div className={classes.header}></div>
{/* BODY */}
<div className={classes.body}></div>
{/* FOOTER */}
<div className={classes.footer}></div>
</nav>
);
};
In some cases, you will need to modified dynamically some classes depending on a component state or variable. To manage this kind of scenarios, assign a function which receive any amount of params in order to modify the classes.
export const Navbar = ({ ariaLabel, className }: NavbarProps) => {
const classes = {
container: cn(className, 'e-flex e-items-center e-px-4'),
header: cn('e-bg-primary-50'),
body: (isOpen: boolean) =>
cn('e-flex-col', {
'e-flex': isOpen,
'e-hidden': !isOpen,
}),
footer: cn('e-text-4xl e-text-primary-50'),
};
return (
<nav aria-label={ariaLabel} className={classes.container} onClick={handleClick}>
{/* HEADER */}
<div className={classes.header}></div>
{/* BODY */}
<div className={classes.body(true)}></div>
{/* FOOTER */}
<div className={classes.footer}></div>
</nav>
);
};