Search code examples
javascriptreactjstypescripttsx

Changing onClick function of React Component to React.FC


I have a Tab component which is a part of tabs structure, but I need to convert it into React.FC. Here is the original and below is what I've done so far, but I'm getting lost around the onclick functionality.

import React, { Component } from 'react';
import PropTypes from 'prop-types';

class Tab extends Component {
 static propTypes = {
      activeTab: PropTypes.string.isRequired,
      label: PropTypes.string.isRequired,
      onClick: PropTypes.func.isRequired
    };

    onClick = () => {
      const { label, onClick } = this.props;
      onClick(label);
    }

    render() {
      const {
        onClick,
        props: {
          activeTab,
          label
        }
      } = this;

      let className = 'tab-list-item';

      if (activeTab === label) {
        className += ' tab-list-active';
      }

      return (
        <li
          className={className}
          onClick={onClick}
        >
          {label}
        </li>
      );
    }
}

export default Tab; 

Here is my very bad attempt, which obviously is very bad

import React from 'react';

/**
 * @function Tab
 */
 const Tab: React.FC = () => {
  

  type Props = {
    activeTab: string;
    label: string;
  }

    const onClick = (props) => {
      const { label, onClick } = props;
      onClick(label);
    }

    const {
      onClick,
      props: {
        activeTab,
        label
      }
    } = this;

      let className = 'tab-list-item';

      if (activeTab === label) {
        className += ' tab-list-active';
      }

      return (
        <li
          className={className}
          onClick={onClick}
        >
          {label}
        </li>
      );
    
}

export default Tab;

Any help would be much much appreciated, thank you!


Solution

  • If you are using typescript, you can define all the component props inside a type/interface and give it to the React.FC type, for example:

    import React from 'react';
    
    interface Props {
      activeTab: string;
      label: string;
      onClick: (label: string) => void; // this means that the onClick param is a function that takes a label of type string as function parameter
    }
    
    // here we create a React functional component and we pass the Props interface to specify the component props
    
    const Tab: React.FC<Props> = (props) => {
      const handleOnClick = () => {
        props.onClick(props.label)
      }
    
      let className = 'tab-list-item';
    
      if (props.activeTab === props.label) {
        className += 'tab-list-active';
      }
    
      return (
        <li
          className={className}
          onClick={props.handleOnClick}
        >
          {props.label}
        </li>
      );  
    }
    
    export default Tab;
    

    If you know how to destructor an object you can clean your function in this way:

    import React from 'react';
    
    interface Props {
      activeTab: string;
      label: string;
      onClick: (label: string) => void; // this means that the onClick param is a function that takes a label of type string as function parameter
    }
    
    // here we create a React functional component and we pass the Props interface to specify the component props
    
    const Tab: React.FC<Props> = ({activeTab, label, onClick}) => {
      const handleOnClick = () => {
       onClick(label)
      }
    
      let className = 'tab-list-item';
    
      if (props.activeTab === label) {
        className += 'tab-list-active';
      }
    
      return (
        <li
          className={className}
          onClick={handleOnClick}
        >
          {label}
        </li>
      );  
    }
    
    export default Tab;