0

Goal

Dynamically create dropdown menus via hooks.


Challenge

When I change a hook value to my dropdown, the dropdown does not open or close. Its stays closed. When I hard code the dropdown in the return, the open and close functions correctly.


Doesn't work Using hooks

///Various required imports are here..


export default  function main(){
 const [testb, state_set_testb] = useState(<div></div>);

function toggle_dropdown_function(toggle_request) {
console.log("fffffffffffffffffffffff",toggle_request)
    state_set_dropdown_open(toggle_request)
  }  

 state_set_testb(<div onMouseEnter={() => toggle_dropdown_function(true)} onMouseLeave={() => toggle_dropdown_function(false)}>
  <Dropdown id="testa" isOpen={dropdownOpen} toggle={toggle_dropdown}>
    <DropdownToggle style={{ backgroundColor: "transparent", border: "none", paddingTop: '8px', paddingBottom: '8px', paddingleft: '10px', paddingRight: '10px', color: "grey", fontSize: "14px " }}
      color="light" >
      othera
      </DropdownToggle >
    <DropdownMenu  >
      <DropdownItem style={{ fontSize: "14px " }}>Some Action</DropdownItem>
    </DropdownMenu>
  </Dropdown>
  </div>)

return <div>{testb}</div>
}


Works Not using hooks

///Various required imports are here..


export default  function main(){

function toggle_dropdown_function(toggle_request) {
console.log("fffffffffffffffffffffff",toggle_request)
    state_set_dropdown_open(toggle_request)
  }  

return <div onMouseEnter={() => toggle_dropdown_function(true)} onMouseLeave={() => toggle_dropdown_function(false)}>
  <Dropdown id="testa" isOpen={dropdownOpen} toggle={toggle_dropdown}>
    <DropdownToggle style={{ backgroundColor: "transparent", border: "none", paddingTop: '8px', paddingBottom: '8px', paddingleft: '10px', paddingRight: '10px', color: "grey", fontSize: "14px " }}
      color="light" >
      othera
      </DropdownToggle >
    <DropdownMenu  >
      <DropdownItem style={{ fontSize: "14px " }}>Some Action</DropdownItem>
    </DropdownMenu>
  </Dropdown>
  </div>
}

2
  • Why do you place React elements in your state variable? This is not the idiomatic approach. Commented Feb 25, 2021 at 11:48
  • How would you accomplish my goal without using hooks? @Martin To add to my goal, the main component will load much before the dropdown fetched data will be ready to render. The dropdown options and the number of dropdowns is fetched. The only way I know how to change the state of the render I through hooks. Commented Feb 25, 2021 at 20:59

1 Answer 1

2

Here is how you could accomplish it. Essentially you have a separate component called Dropdown and you push it to an array of dropdowns.

const { useState } = React;

const Dropdown = () => {
  const [active, setActive] = useState('Select');
  const [isOpen, setOpen] = useState(false);
  const items = ["orange", "pear", "apple"];
  return <div className={`dropdown`}>
    <div onClick={()=> setOpen(!isOpen)} className={"dropdown__header"} >{active}</div >
    {isOpen && 
    <div className={"dropdown__body"}>
      {items.map((item, index) => {
        return <div key={index} onClick={(e) =>  {
            setActive(item);
            setOpen(false);
          }}>{item}</div>
      })}
    </div>
     }
    </div>
} 


const Main = () => {
  const [dropdowns, setDropdowns] = useState([])
  const addDropdowns = () => {
    let updatedDropdowns = [...dropdowns];
    updatedDropdowns.push(<Dropdown />)
    setDropdowns(updatedDropdowns);
  }
  
  return (
    <div className={"main"}>
      <button onClick={addDropdowns}>
        Add Dropdown
      </button>
      {dropdowns.map((dropdown, index) => {
        return <div key={index}>{dropdown}</div>
       })}
    </div>
  )
}

ReactDOM.render(<Main />, document.getElementById('app'))

Here is some codepen.

UPDATE

I managed to use reactstrap using the same approach and I did not notice any problems. Here is a codepen

Sign up to request clarification or add additional context in comments.

2 Comments

Thank you, However this partly works. When I use the Dropdown reactstrap component within your code above, It re-renders/fires constantly
@RandomStuff I did not experience this problem. I updated my answer with a new codepen using the reactstrap library

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.