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
- Only include one React component per file.
- However, multiple Stateless or Pure Components are allowed per file.
- Always use JSX syntax.
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}
/>
- Omit the value of the prop when it's explicitly
true
. eslint: react/jsx-boolean-value
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 haverole="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" />
- Don't use words like "image", "photo", or "picture" in
<img>
alt
props. eslint: jsx-a11y/img-redundant-alt
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" />
- Use only valid, non-abstract ARIA roles. eslint: jsx-a11y/aria-role
Bad
<!-- Not an ARIA role -->
<div role="datepicker" />
<!-- Abstract ARIA role -->
<div role="range" />
Good
<div role="button" />
- Don't use
accessKey
on elements. eslint: jsx-a11y/no-access-key
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
- Wrap JSX tags in parentheses when they span more than one line. eslint: react/jsx-wrap-multilines
Bad
export const Foo = () => {
return <Bar>
<Baz />
</Bar>;
};
Good
export const Foo = () => {
return (
<Bar>
<Baz />
</Bar>
);
};
- Always self-close tags that have no children. eslint: react/self-closing-comp
Bad
<Foo variant="stuff"></Foo>
Good
<Foo variant="stuff" />
- If your component has multiline properties, close its tag on a new line. eslint: react/jsx-closing-bracket-location
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:
- Files that contain React components, or are directly linked to react components should be named in PascalCase i.e.
FlexLayout.tsx
,FlexLayout.test.tsx
, orFlexLayout.stories.tsx
. - Markdown files are usually named in SNAKE_CASE (all caps), i.e.
README.md
orNAMING_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