Skip to content

Deep cloning the theme object on every render hurts performance #1447

@wtlin1228

Description

@wtlin1228
  • I have searched the Issues to see if this bug has already been reported
  • I have tested the latest version

Steps to reproduce

  1. Create an empty flowbite-react project

  2. Add the following code

    import * as React from "react";
    import { getTheme } from "flowbite-react";
    
    const Child = () => {
      const theme = getTheme();
      return <div>child {theme.accordion.content.base}</div>;
    };
    
    function App() {
      const [count, setCount] = React.useState(0);
    
      return (
        <>
          <div>count: {count}</div>
          <button onClick={() => setCount(count + 1)}>inc</button>
          {Array.from({ length: 1000 }).map((_, i) => {
            return <Child key={i} />;
          })}
        </>
      );
    }
  3. Open performance tab of chrome devtool

  4. Record the performance

  5. Click the inc button 100 times

  6. See the result

Current behavior

Screenshot 2024-07-15 at 1 44 23 PM

There are many long tasks. I think the root cause is that we're deep cloning the entire theme object on every render for all components which are using getTheme() API.

// packages/ui/src/helpers/clone-deep.ts
import { isObject } from "./is-object";

export function cloneDeep<T>(source: T): T {
  if (!isObject(source)) {
    return source;
  }

  const output: Record<string, unknown> = {};

  for (const key in source) {
    output[key] = cloneDeep(source[key]);
  }

  return output as T;
}


// packages/ui/src/theme-store/index.tsx
export function getTheme(): FlowbiteTheme {
  return cloneDeep(store.theme);
}

Expected behavior

In such a simple project like this, I'm expecting to have no long tasks:

Screenshot 2024-07-15 at 1 44 29 PM

Context

I'm assessing the new UI library for our internal projects.

Metadata

Metadata

Assignees

Labels

🐛 bugSomething isn't working🚀 enhancementNew feature or requestconfirmedThis bug was confirmed

Type

Projects

No projects

Milestone

No milestone

Relationships

None yet

Development

No branches or pull requests

Issue actions