Home > Software engineering >  How do you pass props to functional components which are to be used using dot notation?
How do you pass props to functional components which are to be used using dot notation?

Time:10-12

I have following code:

import React, { useState } from 'react'

const Dropdown = ({children}) => {
    const [showMenu, setShowMenu] = useState(false)
    const handleShow = () => setShowMenu(!showMenu)
    return <div>{children}</div>
}

const Button = ({children, showMenu}) => {
    return <div onClick={() => showMenu()}>{children}</div>
}

const Menu = ({children}) => <ul>{children}</ul>
const Item = ({children}) => <li>{children}</li>

Dropdown.Button = Button
Dropdown.Menu = Menu
Dropdown.Item = Item

export default Dropdown

I want to pass showMenu from Dropdown function such that it can be accessed by Button component and Menu component

How can I achieve that using functional components

CodePudding user response:

As mentioned in the comments, the most commonly used options are:

1. React Context

const { useState, useContext, createContext } = window.React;

const DropdownContext = createContext({
  showMenu: false,
  setShowMenu: () => true,
});

const Dropdown = ({children}) => {
    const [showMenu, setShowMenu] = useState(false)
    
    return (
      <DropdownContext.Provider value={{ showMenu, setShowMenu }}>
        <div>{children}</div>
      </DropdownContext.Provider>
    );
}

const Button = ({children}) => {
    const { showMenu, setShowMenu } = useContext(DropdownContext);
    
    return <div onClick={() => setShowMenu(!showMenu)}>{children} {showMenu ? 'show' : 'hide'}</div>
}

const Menu = ({children}) => <ul>{children}</ul>
const Item = ({children}) => <li>{children}</li>

Dropdown.Button = Button
Dropdown.Menu = Menu
Dropdown.Item = Item

function App() {
  return (
    <div>
      <Dropdown>
        <Dropdown.Button>Button</Dropdown.Button>
      </Dropdown>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>

2. Controlled Component

const { useState } = window.React;

const Dropdown = ({children}) => {
    return (
      <div>{children}</div>
    );
}

const Button = ({children, onClick, showMenu}) => {
    return <div onClick={onClick}>{children} {showMenu ? 'show' : 'hide'}</div>
}

const Menu = ({children}) => <ul>{children}</ul>
const Item = ({children}) => <li>{children}</li>

Dropdown.Button = Button
Dropdown.Menu = Menu
Dropdown.Item = Item

function App() {
  // with controlled components, the state is managed in a parent component or (global) state 
  const [showMenu, setShowMenu] = useState(false)
  
  return (
    <div>
      <Dropdown showMenu={showMenu}>
        <Dropdown.Button 
          showMenu={showMenu} 
          onClick={() => setShowMenu(!showMenu)}
        >
          Button
        </Dropdown.Button>
      </Dropdown>
    </div>
  );
}

ReactDOM.render(<App />, document.getElementById("app"));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/17.0.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/17.0.1/umd/react-dom.production.min.js"></script>
<div id="app"></div>

  • Related