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>