RouteManager UI coding patterns: React
Published: 2021-07-20 06:32:00


> This is a non-exhaustive list of the coding patterns the [WorkWave RouteManager's](https://www.workwave.com/route-manager/) **front-end** team follows. The patterns are based on years of experience writing, debugging, and refactoring front-end applications with **React and TypeScript** but evolves constantly. Most of the possible improvements and the code smells are detected during the code reviews and the pair programming sessions.

*(please note: I do not work for WorkWave anymore, these patterns will not be updated)*


*(last update: 2022, March)*

- [Prefer duplication over abstraction when dealing with low complexity and boilerplate](#prefer-duplication-over-abstraction-when-dealing-with-low-complexity-and-boilerplate)
- [Avoid "return null" components](#avoid-return-null-components)
- [Move long conditions out of the JSX](#move-long-conditions-out-of-the-jsx)
- [Get JSX combinations/states clear](#get-jsx-combinationsstates-clear)
- [Prefer CSS Variables to optimize Material UI styles](#prefer-css-variables-to-optimize-material-ui-styles)
- [Create component's explicit variants](#create-components-explicit-variants)
- [Avoid naming props with CSS property-like names](#avoid-naming-props-with-css-propertylike-names)

## Prefer duplication over abstraction when dealing with low complexity and boilerplate

Don't get code "smarter" just for the sake of avoiding a bit of duplication. Often, duplication improves readability and gets code ready for future changes.

```tsx
// ❌ don't
const filterValues = {
  all: 'all',
  winners: 'winner',
  losers: 'loser',
}

function FilterBar(props) {
  const isActive = (filter) => filter === props.currentFilter;
  const filters = Object.values(filterValues);

  return filters.map(filter =>
    <div className={isActive(filter) ? 'active' : ''}>{filter}</div>
  )
}

// ✅ do
function FilterBar(props) {
  const { currentFilter } = props

  return <>
    <div className={currentFilter === 'all' ? 'active' : ''}>all</div>
    <div className={currentFilter === 'winner' ? 'active' : ''}>winner</div>
    <div className={currentFilter === 'loser' ? 'active' : ''}>loser</div>
  </>
}
```



## Avoid "return null" components

The component's parent decides if the component is rendered or not.

```tsx
// ❌ don't
function Poll() {
  const [pollEnabled, setPollEnabled] = useState(false)

  return <>
    <TogglePoll setPollEnabled={setPollEnabled} />
    <PollConfirmation pollEnabled={pollEnabled} />
  </>
}

function PollConfirmation(props) {
  if(!props.pollEnabled) return null

  return <>Poll is enabled</>
}

// ✅ do
function Poll() {
  const [pollEnabled, setPollEnabled] = useState(false)

  return <>
    <TogglePoll setPollEnabled={setPollEnabled} />
    {pollEnabled && <PollConfirmation  />}
  </>
}

function PollConfirmation() {
  return <>Poll is enabled</>
}
```

##  Move long conditions out of the JSX

Components' JSX can get unreadable in a while, always move out long conditions.

```tsx
// ❌ don't
function Foo() {
  /* ... rest of the code... */

  return <>
    {(cond1 && status === 'bar' || date === today) && <Bar />}
    {(cond2 && cond3 date !== today) && <Baz />}
  </>
}

// ✅ do
function Foo() {
  /* ... rest of the code... */

  const renderBar = cond1 && status === 'bar' || date === today
  const renderBaz = cond2 && cond3 date !== today

  return <>
    {renderBar && <Bar />}
    {renderBaz && <Baz />}
  </>
}
```

## Get JSX combinations/states clear

JSX with a lot ternaries and logic conditions can make simple cases hard to read. The reader will spend a significant amount of mental energies to detect what is rendered and what isn't.

```tsx
// ❌ don't
function Theme(props) {
  const { theme } = props

  return <>
    {theme === 'dark' ? <div>
      <BlackBackgroundButton />
      <GreyBackgroundButton />
    </div> : <div>
      <WhiteBackgroundButton />
      <SepiaBackgroundButton />
    </div>}

    <ColorsPalette theme={theme} />

    {theme === 'dark' ? <DarkThemeSample /> : <LightThemeSample />}

    {theme === 'light' && <LightThemesList />}
  </>
}

// ✅ do
function Theme(props) {
  const { theme } = props

  switch(theme) {
    case 'dark':
      return <>
        <div>
          <BlackBackgroundButton />
          <GreyBackgroundButton />
        </div>

        <ColorsPalette theme='dark' />
        <DarkThemeSample />
      </>

    case 'light':
      return <>
        <div>
          <WhiteBackgroundButton />
          <SepiaBackgroundButton />
        </div>

        <ColorsPalette theme='light' />
        <LightThemeSample />
        <LightThemesList />
      </>
  }
}
```

The next step is returning a new, dedicated component, for every switch case.

```tsx
// ❌ don't
function Theme(props) {
  const { theme } = props

  switch(theme) {
    case 'dark':
      return <>
        <div>
          <BlackBackgroundButton />
          <GreyBackgroundButton />
        </div>

        <ColorsPalette theme='dark' />
        <DarkThemeSample />
      </>

    case 'light':
      return <>
        <div>
          <WhiteBackgroundButton />
          <SepiaBackgroundButton />
        </div>

        <ColorsPalette theme='light' />
        <LightThemeSample />
        <LightThemesList />
      </>
  }
}

// ✅ do
function Theme(props) {
  switch(props.theme) {
    case 'dark':
      return <DarkTheme />

    case 'light':
      return <LightTheme />
  }
}
```

## Prefer CSS Variables to optimize Material UI styles

Material UI injects a lot of styles into the DOM. CSS variables limit the amount of injected styles for dynamic properties.

```tsx
// ❌ don't
const useStyles = makeStyles({
  foo: props => ({
    backgroundColor: props.backgroundColor,
  }),
});

function MyComponent(props) {
  const classes = useStyles(props);

  return <div className={classes.foo} />
}

// ✅ do
const useClasses = makeStyles({
  foo: { backgroundColor: 'var(--background-color)' }
})

function useStyles(backgroundColor: string) {
  const classes = useClasses()

  const styles = useMemo(() => {
    return {
      foo: { '--background-color': `${backgroundColor}` } as CSSProperties,
    }
  }, [backgroundColor])

  return [classes, styles] as const
}

function MyComponent(props) {
  const [classes, styles] = useStyles(props.backgroundColor)

  return <div className={classes.foo} styles={styles.foo} />
}

```



## Create component's explicit variants

Component explicit variants are more predictable and easy to refactor.

```tsx
// ❌ don't
function Consumer() {
  return (
    <>
      <Button>Click me</Button>
      <Button src="./image.jog" />
    </>
  )
}

// ✅ do
function Consumer() {
  return (
    <>
      <Button variant="text">Click me</Button>
      <Button variant="image" src="./image.jog" />
    </>
  )
}
```

## Avoid naming props with CSS property-like names

Props named like CSS properties create ambiguity, the reader cannot understand if the prop is used to directly set the CSS property or not.

```tsx
// ❌ don't
function Consumer() {
  return (
    <Stack align="left" /> // is "align" used to set CSS Flex' align?
  )
}

// ✅ do
function Consumer() {
  return (
    <Stack variant="left" /> // variant does not sound like a CSS property, nice!
  )
}
```