Samarth Mittal
Samarth Mittal

Reputation: 89

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

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

Upvotes: 0

Views: 738

Answers (1)

Chris
Chris

Reputation: 6631

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>

Upvotes: 3

Related Questions