javascriptreactjsreact-bootstrap

How to use useState to switch between 2 js files with Tabs


Currently working on a project and when clicked on the tab, it should change pages but for some reason its not changing. Only stuck on the overview page. Is there something I'm doing wrong?

import React, {useState} from 'react';
import Tab from 'react-bootstrap/Tab';
import Tabs from 'react-bootstrap/Tabs';
import ClientOverview from '../client_dashboard/client_components/overview';
import ClientImpact from '../client_dashboard/client_components/impacts';
import Box from '@mui/material/Box';
import InputLabel from '@mui/material/InputLabel';
import FormControl from '@mui/material/FormControl';
import Select from '@mui/material/Select';


  const ClientDashContainer = props => {
  const [value, setValue] = useState('overview');

  const handleChange = (event, newValue) => {
    setValue(newValue);
  };
  return(
    <div style={{padding:'2%', backgroundColor:'#f5f5f5', minHeight:'95vh'}}>
        <Box>
            <FormControl style={{width:'15vw', minWidth:'fit-content'}}>
                <InputLabel id="demo-simple-select-label">Sites</InputLabel>
                <Select labelId="demo-simple-select-label" id="demo-simple-select" label="Sites">
                </Select>
            </FormControl>
        </Box>
        <Tabs defaultActiveKey="overview" className="mb-3" justify value={value} onChange={handleChange}>
            <Tab value = 'overview' eventKey="overview" title="Overview"/>
            <Tab value = 'impacts' eventKey="impacts" title="Impacts"/>
        </Tabs>

        {value === 'overview' && <ClientOverview/>}
        {value === 'impacts' && <ClientImpact/>}
    </div>
);
}

export default ClientDashContainer;

Solution

  • The Tabs component uses an onSelect callback to handle selecting a tab, which receives the tab key value. See Tabs API documentation for details.

    Update to use onSelect={handleChange} and update handleChange to receive the tab key.

    Example:

    const ClientDashContainer = (props) => {
      const [value, setValue] = useState("overview");
    
      const handleChange = (value) => setValue(value);
    
      return (
        <div
          style={{ padding: "2%", backgroundColor: "#f5f5f5", minHeight: "95vh" }}
        >
          <Box>
            <FormControl style={{ width: "15vw", minWidth: "fit-content" }}>
              <InputLabel id="demo-simple-select-label">Sites</InputLabel>
              <Select
                labelId="demo-simple-select-label"
                id="demo-simple-select"
                label="Sites"
              ></Select>
            </FormControl>
          </Box>
          <Tabs
            defaultActiveKey="overview"
            className="mb-3"
            justify
            value={value}
            onSelect={handleChange}
          >
            <Tab value="overview" eventKey="overview" title="Overview" />
            <Tab value="impacts" eventKey="impacts" title="Impacts" />
          </Tabs>
    
          {value === "overview" && <ClientOverview />}
          {value === "impacts" && <ClientImpact />}
        </div>
      );
    };
    

    I suggest also using the TabPane component to handle the conditional rendering of your tab content.

    Example:

    import { Tab, Tabs, TabPane } from "react-bootstrap";
    
    ...
    
    <Tabs
      defaultActiveKey="overview"
      className="mb-3"
      justify
      value={value} // can be removed for uncontrolled usage
      onSelect={handleChange} // can be removed for uncontrolled usage
    >
      <Tab value="overview" eventKey="overview" title="Overview" />
      <Tab value="impacts" eventKey="impacts" title="Impacts" />
      <TabPane eventKey="overview">
        <ClientOverview />
      </TabPane>
      <TabPane eventKey="impacts">
        <ClientImpact />
      </TabPane>
    </Tabs>
    

    This also allows you to let the Tabs component control itself, i.e. it is uncontrolled and manages its own state, the value state and onSelect handler aren't needed.