Search code examples
reactjsantd

Ant Design render all the components of tabs when changing a tab and at the first rendering


I'm using And Design for my project in the development and I ran into something weird.

  1. It renders all the components of tabs at the first rendering. As you can see below the console of the snippet, like 'children 1 children 2 children 3'

  2. It renders all the components of tabs when switching tabs as well. You can see the same console log like the previous case.

Am I doing something wrong?

CodeSandbox Example

// demo.js
const App = () => {
  const [tab, setTab] = React.useState(1);

  return (
    <Tabs
      onChange={(key) => {
        setTab(key);
      }}
      type="card"
      accessKey={tab}
      items={new Array(3).fill(null).map((_, i) => {
        const id = String(i + 1);
        return {
          label: `Tab ${id}`,
          key: id,
          children: (
            <div>
              {console.log(`children ${id}`)}
              <span>-----------------{id}</span>
            </div>
          )
        };
      })}
    />
  );
};
// console
children 1 
children 2 
children 3 

I think it should trigger rendering the content of the tab once when changing a tab or at the first rendering.


Solution

  • The array is being recreated on every render of App. App gets rendered every time setTab is called with a different value. If you don't want that to happen, you can declare the array outside the component, or use useMemo.

    const items = new Array(3).fill(null).map((_, i) => {
      const id = String(i + 1);
      return {
        label: `Tab ${id}`,
        key: id,
        children: (
          <div>
            {console.log(`children ${id}`)}
            <span>-----------------{id}</span>
          </div>
        )
      };
    })
    
    const App = () => {
      const [tab, setTab] = React.useState(1);
    
      return (
        <Tabs
          onChange={(key) => {
            setTab(key);
          }}
          type="card"
          accessKey={tab}
          items={items}
        />
      );
    };
    

    OR

    const App = () => {
      const [tab, setTab] = React.useState(1);
    
      const items = useMemo(
        () =>
          new Array(3).fill(null).map((_, i) => {
            const id = String(i + 1);
            return {
              label: `Tab ${id}`,
              key: id,
              children: (
                <div>
                  {console.log(`children ${id}`)}
                  <span>-----------------{id}</span>
                </div>
              ),
            };
          }),
        [] // empty dependency array means never run again
      );
    
      return (
        <Tabs
          onChange={(key) => {
            setTab(key);
          }}
          type="card"
          accessKey={tab}
          items={items}
        />
      );
    };