Keyboard shortcuts

Press or to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

Basic Syntax

If - else

// bad - we don't like inline-if with else branch, harder to read
if (condition) doSomething();
else doSomethingElse();

// good
if (condition) {
    doSomething();
} else {
    doSomethingElse();
}

// also good - inline if without else is fine
if (condition) doSomething();

Spacing

Try to use empty lines as a tool for structuring the code even better.

🔴 Hard to read function without spaces:

export const getPrerequisites = ({ router, device, transport }: PrerequisitesInput) => {
    const excluded = getExcludedPrerequisites(router);
    const prerequisite = getPrerequisiteName({ router, device, transport });
    if (typeof prerequisite === 'undefined') return;
    if (excluded.includes(prerequisite)) return;
    return prerequisite;
};

🟢 Well-arranged code:

export const getPrerequisites = ({ router, device, transport }: PrerequisitesInput) => {
    const excluded = getExcludedPrerequisites(router);
    const prerequisite = getPrerequisiteName({ router, device, transport });

    if (typeof prerequisite === 'undefined') {
        return;
    }

    if (excluded.includes(prerequisite)) {
        return;
    }

    return prerequisite;
};

As you can see, there is no line between excluded and prerequisite – that’s because in this context that separation adds little benefit, instead the constants become the group. Base the groups not only on type of code (method call, if-block, declaration) but on what that code does.

Function parameters

Functions accepting multiple parameters tend to be less readable and more error-prone. This can be solved by wrapping the params (all of them, or just some, i.e. “config” params) in an object, thus effectively naming the parameters. A rule of thumb is to use wrapping for functions with more than two params, but it depends on the specific case.

🔴 Confusing function call with many arguments:

const logAnimalNames = (cat: string, dog: string, guineaPig?: string, showHeading?: boolean) => {
    if (showHeading) {
        console.log('My Animals');
    }
    console.log(cat);
    console.log(dog);
    if (guineaPig) {
        console.log(guineaPig);
    }
};

logAnimalNames('Nancy', 'Rob', null, true);

What is the correct order? Why do I have to specify null for an optional param? What does true mean here?

🟢 Tidy function call with wrapped arguments:

interface LogAnimalParams {
    cat: string;
    dog: string;
    guineaPig?: string;
    showHeading?: boolean;
}

const logAnimalNames = ({ cat, dog, guineaPig, showHeading }: LogAnimalParams) => {
    if (showHeading) {
        console.log('My Animals');
    }
    console.log(cat);
    console.log(dog);
    if (guineaPig) {
        console.log(guineaPig);
    }
};

logAnimalNames({ cat: 'Nancy', dog: 'Rob', showHeading: true });

Conditional rendering

Make sure that a condition in JSX can only be true/false . If it could be 0 or "" , -42 , [] etc. React can render some of those values. In React Native it can also cause text outside Text component!

🔴 Do not use random value as condition

// BAD
{
    value && <Component value={value} />;
}

🟢 Prefer

// typeof hasValue === 'boolean'
{
    hasValue && <Component value={value} />;
}
{
    !!value && <Component value={value} />;
}
if (!value) return null;

return <Component value={value} />;