Skip to main content

React style guide

This style guide is a set of best practices and guidelines for writing Dynatrace Apps. Even though the following is only a guide with no enforced rules, we highly recommend sticking to it to keep consistency across all Dynatrace Apps. You'll also see the link to eslint rules for most of the rules mentioned in this guide.

Note

This style guide is a fork of Airbnb React style guide.

Basic rules

Naming

  • Extensions: Use .tsx extension for React components.
  • Filename: Use PascalCase for filenames. For example, ReservationCard.tsx.
  • Reference naming: Use PascalCase for React components and camelCase for their instances. eslint: react/jsx-pascal-case
Bad
// component
import fooBar from './FooBar';

// instance
const FooBar = <FooBar />;
Good
// component
import FooBar from './FooBar';

// instance
const foobar = <FooBar />;
  • Hooks: Use camelCase for React hooks.
Bad
export const UseFoo = () => { ... }
Good
export const useFoo = () => { ... }
  • Props Naming: Avoid using DOM component prop names for different purposes.
Detailed explanation
Why? People expect props like style and className to mean one specific thing. Varying this API for a subset of your app makes the code less readable and less maintainable, and may cause bugs.
Bad
<Foo style="fancy" />

<Foo className="fancy" />
Good
<Foo variant="fancy" />

Quotes

  • Always use double quotes (") for JSX attributes, but single quotes (') for all other JS. eslint: jsx-quotes
Detailed explanation
Why? Regular HTML attributes also typically use double quotes instead of single, so JSX attributes mirror this convention.
Bad
<Foo bar='bar' />

<Foo style={{ left: "20px" }} />
Good
<Foo bar="bar" />

<Foo style={{ left: '20px' }} />

Props

  • Always use camelCase for prop names, or PascalCase if the prop value is a React component.
Bad
<Foo
UserName="hello"
phone_number={12345678}
/>
Good
<Foo
userName="hello"
phoneNumber={12345678}
Component={SomeComponent}
/>
Bad
<Foo hidden={true} />
Good
<Foo hidden />
  • Avoid using an array index as key prop, prefer a stable id. (Why?)
Bad
todos.map((todo, index) => <Todo {...todo} key={index} />);
Good
todos.map((todo) => <Todo {...todo} key={todo.id} />);
  • Use spread props sparingly.
Detailed explanation
Why? Otherwise, you're more likely to pass unnecessary props down to components. For React v15.6.1 and older, you could pass invalid HTML attributes to the DOM.

Exceptions:

  • Spreading objects with known, explicit props. This can be particularly useful when testing React components with Mocha's beforeEach construct.
export default function Foo() {
const props = {
text: '',
isPublished: false,
};

return <div {...props} />;
}
  • To filter out unnecessary props when possible.
Caution
export const Foo = (props) => {
return <Bar {...props} />;
};
Better
// filter out unnecessary props
export const Foo = (props) => {
const { ignoredProp, ...barProps } = props;

return <Bar {...barProps} />;
};

// wrapped internal component
export const Foo = (props) => {
return <WrappedFoo {...props} />;
};

// explicit props object
export const Foo = () => {
const barProps = {
name: 'bar',
baz: 123,
};

return <Bar {...barProps} />;
};

Accessibility

  • Always include an alt prop on <img> tags. If the image is presentational, alt can be an empty string or the <img> tag needs to have role="presentation". eslint: jsx-a11y/alt-text
Bad
<img src="hello.jpg" />
Good
<img src="hello.jpg" alt="Me waving hello" />

<!-- Presentational image -->
<img src="hello.jpg" alt="" />
<img src="hello.jpg" role="presentation" />
Detailed explanation
Why? Screenreaders already announce img elements as images, so there is no need to include this information in the alt text.
Bad
<img src="hello.jpg" alt="Picture of me waving hello" />
Good
<img src="hello.jpg" alt="Me waving hello" />
Bad
<!-- Not an ARIA role -->
<div role="datepicker" />

<!-- Abstract ARIA role -->
<div role="range" />
Good
<div role="button" />
Detailed explanation
Why? Inconsistencies between keyboard shortcuts and keyboard commands used by people using screenreaders and keyboards complicate accessibility.
Bad
<button accesskey="s">Click me!</button>
Good
<button>Click me!</button>

JSX

Bad
export const Foo = () => {
return <Bar>
<Baz />
</Bar>;
};
Good
export const Foo = () => {
return (
<Bar>
<Baz />
</Bar>
);
};
Bad
<Foo variant="stuff"></Foo>
Good
<Foo variant="stuff" />
Bad
<Foo
bar="bar"
baz="baz" />
Good
<Foo
bar="bar"
baz="baz"
/>

Files and directories

For the most part, files and directories should be named in kebab-case, with some exceptions:

  1. Files that contain React components, or are directly linked to react components should be named in PascalCase i.e. FlexLayout.tsx, FlexLayout.test.tsx, or FlexLayout.stories.tsx.
  2. Markdown files are usually named in SNAKE_CASE (all caps), i.e. README.md or NAMING_CONVENTIONS.md.

Applicable to individual component directories, a general directory structure like the following has proven to increase navigability. Empty directories should be omitted.

  • component
    • contexts - Containing react contexts.
    • hooks - Containing component specific hooks.
    • providers - Containing provider components.
    • types - Containing general type information (component props should be located with the component).
    • util - Containing further utility functions.
    • Component.test.tsx
    • Component.tsx
    • index.ts
Still have questions?
Find answers in the Dynatrace Community