简体   繁体   中英

How to keep track of the state in functional component in Reactjs?

I revealed all the drop-down list from the nav items on hover instead of click by creating a separate state variable for all the three different NavDropDown and it worked. Is there any other shortcuts and alternatives beside that?

Currently my code is as follows:

function Navigation(){
  const [isOpenAbout, setIsOpenAbout] = useState(false);
  const [isOpenServices, setIsOpenServices] = useState(false);
  const [isOpenContact, setIsOpenContact] = useState(false);
  return (
   <Nav className="ml-auto">
    <NavDropdown
      title="About"
      onMouseEnter = { () => setIsOpenAbout(true) }
      onMouseLeave = { () => setIsOpenAbout(false) }
      show={ isOpenAbout }
    >
      <NavDropdown.Item href="#action/1.1">Who we are</NavDropdown.Item>
      <NavDropdown.Item href="#action/2.2">
        How we work
      </NavDropdown.Item>
      <NavDropdown.Item href="#action/2.2">
        Certifications
      </NavDropdown.Item>
    </NavDropdown>

    <NavDropdown
      title="Services"
      onMouseEnter = { () => setIsOpenServices(true) }
      onMouseLeave = { () => setIsOpenServices(false) }
      show={ isOpenServices }
    >
      <NavDropdown.Item href="#action/2.1">
        Cloud Digital Transformation
      </NavDropdown.Item>
      <NavDropdown.Item href="#action/2.2">
        Expert Cloud Advise and Support
      </NavDropdown.Item>
      <NavDropdown.Item href="#action/2.3">
        Software Development
      </NavDropdown.Item>
      <NavDropdown.Item href="#action/2.4">
        Dedicated Teams
      </NavDropdown.Item>
    </NavDropdown>
    <Nav.Link href="https://www.genesecloud.academy/" target="_blank">
      Cloud Academy
    </Nav.Link>
    <NavDropdown
      title="Contact"
      onMouseEnter={() => setIsOpenContact(true)}
      onMouseLeave={() => setIsOpenContact(false)}
      show={isOpenContact}
    >
      <NavDropdown.Item href="#sales">Sales</NavDropdown.Item>
      <NavDropdown.Item href="#support">Support</NavDropdown.Item>
    </NavDropdown>
  </Nav>

  )
}

What's the best possible way to keep the track of the state? It would have been better if anyone could assist me out.

You can improve your code by using only 1 state object, this is more general and easier to extend in the future:

function Navigation(){

  const defaultState = {
    about: false,
    services: false,
    contact: false
  };

  const show = function (dropdownElement) {
    const newState = Object.assign(this.dropdownState);
    newState[dropdownElement] = true;
    setDropdownState(newState);
  };

  const hide = function(dropdownElement) {
    const newState = Object.assign(this.dropdownState);
    newState[dropdownElement] = false;
    setDropdownState(newState);
  }

  const [dropdownState, setDropdownState] = useState(defaultState);

  return (
   <Nav className="ml-auto">
    <NavDropdown
      title="About"
      onMouseEnter = { () => show("about") }
      onMouseLeave = { () => hide("about") }
      show={ this.dropdownState.about }
    >
      <NavDropdown.Item href="#action/1.1">Who we are</NavDropdown.Item>
      <NavDropdown.Item href="#action/2.2">
        How we work
      </NavDropdown.Item>
      <NavDropdown.Item href="#action/2.2">
        Certifications
      </NavDropdown.Item>
    </NavDropdown>

    <NavDropdown
      title="Services"
      onMouseEnter = { () => show("services") }
      onMouseLeave = { () => hide("services") }
      show={ this.dropdownState.services }
    >
      <NavDropdown.Item href="#action/2.1">
        Cloud Digital Transformation
      </NavDropdown.Item>
      <NavDropdown.Item href="#action/2.2">
        Expert Cloud Advise and Support
      </NavDropdown.Item>
      <NavDropdown.Item href="#action/2.3">
        Software Development
      </NavDropdown.Item>
      <NavDropdown.Item href="#action/2.4">
        Dedicated Teams
      </NavDropdown.Item>
    </NavDropdown>
    <Nav.Link href="https://www.genesecloud.academy/" target="_blank">
      Cloud Academy
    </Nav.Link>
    <NavDropdown
      title="Contact"
      onMouseEnter={() => show("contact")}
      onMouseLeave={() => hide("contact")}
      show={ this.dropdownState.contact }
    >
      <NavDropdown.Item href="#sales">Sales</NavDropdown.Item>
      <NavDropdown.Item href="#support">Support</NavDropdown.Item>
    </NavDropdown>
  </Nav>
  )
}

In your <Navigation /> component you could setup a property called, activeDropdown . On onMouseEnter you could set the state of the title of the <NavDropdown /> like you already are and clear activeDropdown on onMouseLeave . Lastly in your show prop you can compare the title to the activeDropdown :

function Navigation(){
  const [activeDropdown, setActiveDropdown] = useState("");

  const clearActiveDropdown () => setActiveDropdown("");
  ...
  <Nav className="ml-auto">
    <NavDropdown
      title="About"
      onMouseEnter={ () => setActiveDropdown("about") }
      onMouseLeave={ clearActiveDropdown }
      show={ activeDropdown === "about" }
    >
      ...
    </NavDropdown>
  </Nav>
  ...
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM