skip to Main Content

I am just starting in ReactJS and have a very basic doubt which I can’t seem to work around without manipulating some complex things which I don’t yet understand (according to some answers here)

Here is a brief example of my problem –

I have a specific implementation, where the "{console.log(‘Test log’)}" inserted in this code snippet from the official page of Material UI, should not be logged on tab Switching. Currently, every tab switch, logs it in the console.

In the actual code, I have a function call at the place of console.log, which I don’t want to perform on tab switching, currently, every time I switch any tab, it makes a function call because currently rendering the tab component basically means calling that function again and again. This is official publicly available Material UI code where I have added just a console.log. I can’t actually post the code implementation due to privacy restrictions.

import * as React from 'react';
import PropTypes from 'prop-types';
import Tabs from '@mui/material/Tabs';
import Tab from '@mui/material/Tab';
import Typography from '@mui/material/Typography';
import Box from '@mui/material/Box';

function CustomTabPanel(props) {
  const { children, value, index, ...other } = props;

  return (
    <div
      role="tabpanel"
      hidden={value !== index}
      id={`simple-tabpanel-${index}`}
      aria-labelledby={`simple-tab-${index}`}
      {...other}
    >
      {value === index && (
        <Box sx={{ p: 3 }}>
          <Typography>{children}</Typography>
        </Box>
      )}
    </div>
  );
}

CustomTabPanel.propTypes = {
  children: PropTypes.node,
  index: PropTypes.number.isRequired,
  value: PropTypes.number.isRequired,
};

function a11yProps(index) {
  return {
    id: `simple-tab-${index}`,
    'aria-controls': `simple-tabpanel-${index}`,
  };
}

export default function BasicTabs() {
  const [value, setValue] = React.useState(0);

  const handleChange = (event, newValue) => {
    setValue(newValue);
  };

  return (
    <Box sx={{ width: '100%' }}>
      <Box sx={{ borderBottom: 1, borderColor: 'divider' }}>
        <Tabs value={value} onChange={handleChange} aria-label="basic tabs example">
          <Tab label="Item One" {...a11yProps(0)} />
          <Tab label="Item Two" {...a11yProps(1)} />
          <Tab label="Item Three" {...a11yProps(2)} />
        </Tabs>
      </Box>
      <CustomTabPanel value={value} index={0}>
        Item One
      </CustomTabPanel>
      <CustomTabPanel value={value} index={1}>
        Item Two
       {console.log('Test Log')}
      </CustomTabPanel>
      <CustomTabPanel value={value} index={2}>
        Item Three
      </CustomTabPanel>
    </Box>
  );
}

I have tried changing these settings while making the Tabs component, but they also don’t seem to work :

<Tabs
    
    unmountOnExit={true}
    mountOnEnter={true}
    transition={false}>

{children}

</Tabs>

2

Answers


  1. When should the special function be executed?

    1.) If you want your code to be executed on switching to specific tab, you can do your call inside handleChange:

    const handleChange = (event, newValue) => {
      if(newValue == 1) {
        console.log('Test Log')
      }
      setValue(newValue);
    };
    

    2.) If you want to call it once (on the first render of your component), you can use useEffect with an empty dependency list:

    import React, { useEffect, useState } from 'react'
    ...
    useEffect(() => {
      console.log('Test Log')
    }, [])
    

    3.) If you want to call it every time a specific state of your component changed, you can give useEffect the state as a dependency:

    import React, { useEffect, useState } from 'react'
    ...
    useEffect(() => {
      console.log('Test Log')
    }, [myState])
    
    Login or Signup to reply.
  2. Add an option to CustomTabPanel called onFirstShow. If onFirstShow exists, the tab is not hidden, and it wasn’t shown before (using a ref to track), the onFirstShow function is called:

    function CustomTabPanel({ children, value, index, onFirstShow, ...other }) {
      const shown = useRef(false);
      const hidden = value !== index;
      
      useEffect(() => {
        if(!shown.current && !hidden && typeof onFirstShow === 'function') {
          onFirstShow();
          
          shown.current = true;
        }
      }, [called, hidden, onFirstShow]);
    
      return (
        <div
          role="tabpanel"
          hidden={value !== index}
          id={`simple-tabpanel-${index}`}
          aria-labelledby={`simple-tab-${index}`}
          {...other}
        >
          {!hidden && (
            <Box sx={{ p: 3 }}>
              <Typography>{children}</Typography>
            </Box>
          )}
        </div>
      );
    }
    

    And then use it when rendering the CustomTabPanel:

      <CustomTabPanel 
        onFirstShow={() => console.log('Test Log')}
        value={value}
        index={1}>
        Item Two
      </CustomTabPanel>
    
    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search