andywer/react-usestyles

Allow eager styles preparation

andywer opened this issue · 2 comments

There are some opt-in options available to improve the performance, but there is one thing they cannot improve:

Every styles object has to be prepared initially and that happens each component mount. This preparation primarily means separation between static and dynamic style rules/declarations (function values).

Especially for components that get instantiated a lot that might have a serious performance impact.

Possible solution

Could pass a reference to the component to useStyles(), so the styles can be prepared only once for each component instead of once for each component instance.

import { useStyles } from "@andywer/style-hook"
import React from "react"

function Button () {
  const classNames = useStyles({
    default: {
      background: theme => props.background || theme.button.background.default
      // ...
    }
  }, Button, [props.background])
  return // ...
}

Additional benefit:

If we have the component reference, we have access to the component's name. Could use that for a better development / debugging experience (i.e. put component name on style tags).

Can also stop JSON.stringify()-ing the styles for deduplication when having a component reference. Will improve the overall performance even more!

First idea (dismissed)

import { prepareStyles, useStyles } from "@andywer/style-hook"
import React from "react"

const buttonStyles = prepareStyles({
  // ...
})

function Button () {
  const classNames = useStyles(buttonStyles())
  return // ...
}

If we also need access to the component props:

import { prepareStyles, useStyles } from "@andywer/style-hook"
import React from "react"

const buttonStyles = prepareStyles({
  default: {
    background: (theme, props) => props.background || theme.button.background.default
  }
  // ...
})

function Button () {
  const classNames = useStyles(buttonStyles(props), [props.background])
  return // ...
}

Maybe we can even get around passing the component reference manually in the long term... reactjs/rfcs#68 (comment)