LOTUSMS
LOTUSMS

Reputation: 10240

Setting the state on one item only

How can I reverse or toggle the state only the item clicked. So far all of the tab classes are toggling to active. But I need only the one clicked. I'm teaching myself hooks. so no class component solutions please

  const  App = () => { 
      const tabItems = [
        {
          id:"1",
          tabname: "Unsplash",
          datatab: "unsplash",
          template: <Unsplash/>
        },
        {
          id:"2",
          tabname: "YouTube",
          datatab: "youtube",
          template: <Youtube/>
        },
        {
          id:"3",
          tabname: "Wikipedia",
          datatab: "wiki",
          template: <Wikipedia/>
        },
        {
          id:"4",
          tabname: "DropdownApp",
          datatab: "dropdownapp",
          template: <DropdownApp/>
        },
      ]        

      const [activeTab, setActiveTab] = useState(false)

      const tabs = tabItems.map((tab, i) => {
        return (
          <span
            className={`item ${activeTab ? 'active' : ''}`} 
            key={tab.id}
            data-tab={tab.datatab}
            onClick={() => setActiveTab(!activeTab)}>
            {tab.tabname}
          </span>
        )
      })

      const tabPanels = tabItems.map((tabPanel) => {
        return (
          <div 
            key={tabPanel.id} 
            className={`ui bottom attached tab segment ${activeTab ? 'active' : ''}`}
            data-tab={tabPanel.datatab}>
            {tabPanel.template}
          </div>
        )
      })

      return (
        <div className="App">
          <div className="ui main text" style={{padding: '20px'}}>      
            <div className="ui top attached tabular menu">
              {tabs}
            </div>
            {tabPanels}
          </div>
        </div>
      );
    }

Upvotes: 0

Views: 38

Answers (1)

Domino987
Domino987

Reputation: 8774

You are only tracking if the tab are selected or not, not which one, since you have one state for all tabs. You need to track, which tab is selected:

const  App = () => { 
      const tabItems = [
        {
          id:"1",
          tabname: "Unsplash",
          datatab: "unsplash",
          template: <Unsplash/>
        },
        {
          id:"2",
          tabname: "YouTube",
          datatab: "youtube",
          template: <Youtube/>
        },
        {
          id:"3",
          tabname: "Wikipedia",
          datatab: "wiki",
          template: <Wikipedia/>
        },
        {
          id:"4",
          tabname: "DropdownApp",
          datatab: "dropdownapp",
          template: <DropdownApp/>
        },
      ]        

      const [activeTab, setActiveTab] = useState("") // Track the id

      const tabs = tabItems.map((tab, i) => {
        return (
          <span
            className={`item ${activeTab === tab.id ? 'active' : ''}`} // Check if the tab ids are the same
            key={tab.id}
            data-tab={tab.datatab}
            onClick={() => setActiveTab(tab.id)}> // Save the id instead of a boolean
            {tab.tabname}
          </span>
        )
      })

      const tabPanels = tabItems.map((tabPanel) => {
        return (
          <div 
            key={tabPanel.id} 
            className={`ui bottom attached tab segment ${activeTab === tab.id ? 'active' : ''}`}
            data-tab={tabPanel.datatab}>
            {tabPanel.template}
          </div>
        )
      })

      return (
        <div className="App">
          <div className="ui main text" style={{padding: '20px'}}>      
            <div className="ui top attached tabular menu">
              {tabs}
            </div>
            {tabPanels}
          </div>
        </div>
      );
    }

If you want to unselect a tab, you would need to modify the onClick:

setTab = (id) => {
   setActiveTab(tab => tab === id ? "" : id);
}

and invoke it with:

<span
   onClick={() => setTab(tab.id)}> 

Upvotes: 1

Related Questions