Search code examples
reactjssemantic-ui

Unable to convert class component to function component


This is how semantic-ui menu component looks like:

import React, { Component } from 'react'
import { Input, Menu, Segment } from 'semantic-ui-react'

export default class MenuExamplePointing extends Component {
  state = { activeItem: 'home' }

  handleItemClick = (e, { name }) => this.setState({ activeItem: name })

  render() {
    const { activeItem } = this.state

    return (
      <div>
        <Menu pointing>
          <Menu.Item
            name='home'
            active={activeItem === 'home'}
            onClick={this.handleItemClick}
          />
          <Menu.Item
            name='messages'
            active={activeItem === 'messages'}
            onClick={this.handleItemClick}
          />
          <Menu.Item
            name='friends'
            active={activeItem === 'friends'}
            onClick={this.handleItemClick}
          />
          <Menu.Menu position='right'>
            <Menu.Item>
              <Input icon='search' placeholder='Search...' />
            </Menu.Item>
          </Menu.Menu>
        </Menu>

        <Segment>
          <img src='https://react.semantic-ui.com/images/wireframe/paragraph.png' />
        </Segment>
      </div>
    )
  }
}

I am trying to convert this into function component. This is how my function component looks like:

import React, { useState } from "react";
import { Menu, Segment } from "semantic-ui-react";

function App() {
  const [activeItem, setActiveItem] = useState("home");

  const setActiveItemOnClick = e => {
    alert(e.target.name);
    setActiveItem(e.target.name);
  };

  return (
    <div>
      <Menu pointing>
        <Menu.Item
          name="home"
          active={activeItem === "home"}
          onClick={setActiveItemOnClick}
        />
        <Menu.Item
          name="messages"
          active={activeItem === "messages"}
          onClick={setActiveItemOnClick}
        />
        <Menu.Item
          name="friends"
          active={activeItem === "friends"}
          onClick={setActiveItemOnClick}
        />
      </Menu>

      <Segment>
        <img src="https://react.semantic-ui.com/images/wireframe/paragraph.png" />
      </Segment>
    </div>
  );
}

export default App;

This works fine for the most part except that when I click on the menu item, e.target.name is empty.

Am I doing something wrong here?


Solution

  • This is the fixed code

    function App() {
      const [activeItem, setActiveItem] = useState("home");
    
      const setActiveItemOnClick = (e, { name }) => {
        console.log(name);
        setActiveItem(name);
      };
    
      return (
        <div>
          <MenuExamplePointing />
          <Menu pointing>
            <Menu.Item
              name="home"
              active={activeItem === "home"}
              onClick={setActiveItemOnClick}
            />
            <Menu.Item
              name="messages"
              active={activeItem === "messages"}
              onClick={setActiveItemOnClick}
            />
            <Menu.Item
              name="friends"
              active={activeItem === "friends"}
              onClick={setActiveItemOnClick}
            />
          </Menu>
    
          <Segment>
            <img src="https://react.semantic-ui.com/images/wireframe/paragraph.png" />
          </Segment>
        </div>
      );
    }
    

    In your class component you are destructuring the second parameter of handleItemClick

    handleItemClick = (e, { name }) => this.setState({ activeItem: name })
                              ^
    

    You can do the same for your handler in your functional component

    const setActiveItemOnClick = (e, { name }) => {
      console.log(name);
      setActiveItem(name);
    };
    

    If you take a look at the DOM, the name prop doesn't get passed forward itemList DoM

    therefore it is not accessibleby e.target if you take a look at the docs of the Menu.item component, you can see that the original props that were sent to the Menu.item component are accessible from the data prop of the onClick function