question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

sx prop re-renders

See original GitHub issue

I really like the API of being able to pass styles directly to components inline using sx.

The one downside is that it can trigger re-renders on every parent render, since the styles create a new sx object prop.

A few possible solutions:

  1. Follow a styled components type approach, and create a styled function:
import { styled, Box } from 'dripsy'

const Page = styled(Box)(props => ({
  backgroundColor: ['primary', 'secondary']
}))
  1. Could there be some sort of smart memoization / deep comparison that checks the sx prop, and doesn’t re-render if it matches? I am usually very, very way of deep comparison, as it’s not recommended by react in almost all cases (see here.)

One option could be to JSON.stringify the sx prop and compare if this changed. The problem with that approach is that styles can a) contain animated values, and b) have functions:

// not JSON serializable...
<View sx={{ height: theme => theme.sizes[1] }} />

Basically, it would be nice if there were no concerns about passing style props inline for performance. I haven’t done extensive testing on this, but I imagine it could have some downsides.

Issue Analytics

  • State:closed
  • Created 3 years ago
  • Comments:30 (29 by maintainers)

github_iconTop GitHub Comments

2reactions
nandorojocommented, Sep 29, 2021

Dripsy v3 will automatically memoize the sx prop under the hood using stableHash from swr. See here

2reactions
intergalacticspacehighwaycommented, Sep 18, 2021

@nandorojo @cmaycumber Do you think a babel plugin like this might be worth?

function App() {
  return (
    <>
      <View sx={{ backgroundColor: "black" }} />
      <View sx={{ marginTop: "100", paddingVertical: 20 }} />
    </>
  );
}

Converts to

import { useMemo as _useMemo } from "react";

function App() {
  const _sx = _useMemo(
    () => ({
      1: {
        backgroundColor: "black",
      },
      2: {
        marginTop: "100",
        paddingVertical: 20,
      },
    }),
    []
  );

  return (
    <>
      <View sx={_sx["1"]} />
      <View sx={_sx["2"]} />
    </>
  );
}

Cases

1. sx remains untouched if it contains any variables.

function App() {
  const padding = 10;
  return (
    <>
      <View sx={{ backgroundColor: "black", padding }} />
      <View sx={{ marginTop: "100", paddingVertical: 20 }} />
    </>
  );
}

will be converted to

import { useMemo as _useMemo } from "react";

function App() {
  const _sx = _useMemo(
    () => ({
      2: {
        marginTop: "100",
        paddingVertical: 20,
      },
    }),
    []
  );

  const padding = 10;
  return (
    <>
      <View
        sx={{
          backgroundColor: "black",
          padding,
        }}
      />
      <View sx={_sx["2"]} />
    </>
  );
}

This case is considered because when it contains a variable, it gets harder to find location to put useMemo. e.g.

function App() {
    if (boolean) return null;

    const a = 10;
    return <View  sx={{padding: a}} />
}

Here, we might have to move the variable a above the condition and add useMemo.

2. Nit pick but it’s hard to tell if a function returning JSX will be used as a react component.

e.g.

const Component = () => <View sx={{bg: "black" }} />

can be used as <Component /> or Component();

This makes it difficult to recognize whether useMemo should be added or not, one heuristic I can think of is if a function name starts with a capital letter it can be considered as a react component and try to memoize sx props.

Read more comments on GitHub >

github_iconTop Results From Across the Web

css - extending sx props to memorize value and avoid rerenders
So I was wandering if there was a way to add a useMemo wrapped version of the MUI sx props. How would I...
Read more >
React MUI CardMedia API - GeeksforGeeks
Props list: children: It is used to denote the content of the card. classes: It is to override or extend the styles applied...
Read more >
How to customize - Material UI - MUI
The sx prop is the best option for adding style overrides to a single instance of a component in most cases. It can...
Read more >
Overriding styles with the sx prop | Primer React
The sx prop allows ad-hoc styling that is still theme-aware. Declare the styles you want to apply in CamelCase object notation, ...
Read more >
Prevent Unnecessary Component Rerenders with React memo
With React.memo , you can now pass a stateless functional component to it and it will ensure that it does not rerender unless...
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found