React ant design Tab icon change different status

2.9k views Asked by At

I'm using a react typescript project with ant design tab, every time, when I click on the 2nd tab, the icon on the 1st tab should be changed to lock and the 2nd tab will have the book icon. If I then again click the 1st tab, it will display the book icon instead and the 2nd tab changed to lock.

stazkblitz here

code here

import React from 'react';
import ReactDOM from 'react-dom';
import 'antd/dist/antd.css';
import './index.css';
import { Tabs } from 'antd';
import { FileDoneOutlined, LockOutlined } from '@ant-design/icons';

const { TabPane } = Tabs;

ReactDOM.render(
  <Tabs defaultActiveKey="2">
    <TabPane
      tab={
        <span>
         <FileDoneOutlined />
          Tab 1
        </span>
      }
      key="1"
    >
      Tab 1
    </TabPane>
    <TabPane
      tab={
        <span>
    < LockOutlined/>
          Tab 2
        </span>
      }
      key="2"
    >
      Tab 2
    </TabPane>
  </Tabs>,
  document.getElementById('container'),
);
2

There are 2 answers

0
Zachary Haber On BEST ANSWER

The easiest way is to switch to using the Tabs as a controlled component, so you can make changes to the render based on the currently active tab.

Then just use a ternary operator to switch out the Icon for each tab based on if it's active

Working Stackblitz: https://stackblitz.com/edit/react-uwhrx3-oajdjw?file=index.js

Here's the code:

function TabPage() {
  // useState to make the Tabs controlled
  const [tab, setTab] = useState("2");
  return (
    <Tabs
      activeKey={tab}
      onChange={key => {
        setTab(key);
      }}
    >
      <TabPane
        tab={
          <span>
            {/* Use a ternary operator to conditionally render the Icons */}
            {tab === "1" ? <FileDoneOutlined /> : <LockOutlined />}
            Tab 1
          </span>
        }
        key="1"
      >
        Tab 1
      </TabPane>
      <TabPane
        tab={
          <span>
            {tab === "2" ? <FileDoneOutlined /> : <LockOutlined />}
            Tab 2
          </span>
        }
        key="2"
      >
        Tab 2
      </TabPane>
    </Tabs>
  );
}

Just for fun, I set it up so that the Tabs uses a configuration array to set up the panes.

https://stackblitz.com/edit/react-uwhrx3-vnkdcq?file=index.js

import React, { useState } from "react";
import ReactDOM from "react-dom";
import "antd/dist/antd.css";
import "./index.css";
import { Tabs } from "antd";
import {
  FileDoneOutlined,
  LockOutlined,
  RadarChartOutlined
} from "@ant-design/icons";

const { TabPane } = Tabs;

function TabPage() {
  // useState to make the Tabs controlled
  const [tab, setTab] = useState("1");

  /**
   * @type {{title: React.ReactNode; content: React.ReactNode, icon?: Icon}[]}
   *
   * This config array will generate the tabs with the title and content desired
   */
  const tabs = [
    { title: "Tab 1", content: "Tab 1" },
    {
      title: "Radar Chart",
      content: "This is the best chart you'll see",
      icon: <RadarChartOutlined />
    },
    { title: "Tab 3", content: "Tab 3" }
  ];
  return (
    <Tabs
      activeKey={tab}
      onChange={key => {
        setTab(key);
      }}
    >
      {tabs.map(({ title, content, icon }, index) => {
        const key = `${index}`;
        return (
          <TabPane
            key={key}
            tab={
              <span>
                {tab === key ? icon ?? <FileDoneOutlined /> : <LockOutlined />}
                {title}
              </span>
            }
          >
            {content}
          </TabPane>
        );
      })}
    </Tabs>
  );
}

ReactDOM.render(<TabPage />, document.getElementById("container"));

0
Mohammad Harith On

Here is the solution with a reusable component for the tabs' title.

Example in stackblitz