typescript.react.best-practice.define-styled-components-on-module-level.define-styled-components-on-module-level

profile photo of semgrepsemgrep
Author
102
Download Count*

By declaring a styled component inside the render method of a react component, you are dynamically creating a new component on every render. This means that React will have to discard and re-calculate that part of the DOM subtree on each subsequent render, instead of just calculating the difference of what changed between them. This leads to performance bottlenecks and unpredictable behavior.

Run Locally

Run in CI

Defintion

rules:
  - id: define-styled-components-on-module-level
    patterns:
      - pattern-inside: |
          import styled from 'styled-components';
          ...
      - pattern-either:
          - pattern-inside: |
              function $FUNC(...) {
                ...
              }
          - pattern-inside: |
              class $CLASS {
                ...
              }
      - pattern-either:
          - pattern: |
              styled.$EL`...`;
          - pattern: |
              styled($EL)`...`;
    message: By declaring a styled component inside the render method of a react
      component, you are dynamically creating a new component on every render.
      This means that React will have to discard and re-calculate that part of
      the DOM subtree on each subsequent render, instead of just calculating the
      difference of what changed between them. This leads to performance
      bottlenecks and unpredictable behavior.
    metadata:
      references:
        - https://styled-components.com/docs/faqs#why-should-i-avoid-declaring-styled-components-in-the-render-method
      category: best-practice
      technology:
        - react
      license: Commons Clause License Condition v1.0[LGPL-2.1-only]
    languages:
      - typescript
      - javascript
    severity: WARNING

Examples

define-styled-components-on-module-level.tsx

import styled from "styled-components";

// ok: define-styled-components-on-module-level
const ArbitraryComponent = styled.div`
  color: blue;
`
// ok: define-styled-components-on-module-level
const ArbitraryComponent2 = styled(ArbitraryComponent)`
  color: blue;
`

function FunctionalComponent() {
  // ruleid: define-styled-components-on-module-level
  const ArbitraryComponent3 = styled.div`
    color: blue;
  `
  return <ArbitraryComponent3 />
}

function FunctionalComponent2() {
  // ruleid: define-styled-components-on-module-level
  const ArbitraryComponent3 = styled(FunctionalComponent)`
    color: blue;
  `
  return <ArbitraryComponent3 />
}

class ClassComponent {
  public render() {
    // ruleid: define-styled-components-on-module-level
    const ArbitraryComponent4 = styled.div`
        color: blue;
    `
    return <ArbitraryComponent4 />
  }
}