简体   繁体   中英

remove active state from react component

I'm pretty sure what I'm doing is considered an "anti-pattern". I just don't really know react all that well, and I haven't really used JS in any real way since around the time ECMA Script 6 was released.

Here's my "./js/component/header.js". Essentially, I want to turn off the blue of the "NavDropDown" after it's been clicked.

import HeaderBehavior from '../behavior/header.js';

import React from 'react'
import {
  Nav,
  NavDropdown
} from 'react-bootstrap'

const Header = () => {
  const headerBehavior = new HeaderBehavior();
  const fileClick = (eventKey, elem) => {
    headerBehavior.file(eventKey);
    elem.target.classList.remove("active");
  };
    return (
    <Nav variant="fill">
      <NavDropdown title="File" onSelect={fileClick}>
        <NavDropdown.Item eventKey="new">New</NavDropdown.Item>
        <NavDropdown.Item eventKey="open">Open</NavDropdown.Item>
        <NavDropdown.Item eventKey="save">Save</NavDropdown.Item>
        <NavDropdown.Item eventKey="save_as">Save As</NavDropdown.Item>
      </NavDropdown>
    </Nav>
    )
}

export default Header;

I'm doing my best to avoid managing the CSS directly, if I don't know JS all that well, I REALLY don't know CSS. Is this an acceptable pattern?

In react generally you don't want to access and edit the DOM directly, which is what you are doing with

elem.target.classList.remove("active");

What you can do instead is use className prop. You should create a string based on a state that holds the active eventKey.

Take a look at a very similar case in the official docs: https://reactjs.org/docs/faq-styling.html

So this is a more react way:

const Header = () => {
  const headerBehavior = new HeaderBehavior();
  
  const [active, setActive] = useState();
  
  const fileClick = (eventKey, elem) => {
    headerBehavior.file(eventKey);
    setActive(eventKey);
  };
  
  const getClassName = (eventKey) => {
    return eventKey === active ? "active" : null;
  };
  
    return (
    <Nav variant="fill">
      <NavDropdown title="File" onSelect={fileClick}>
        <NavDropdown.Item className={getClassName("new")} eventKey="new">New</NavDropdown.Item>
        <NavDropdown.Item className={getClassName("open")} eventKey="open">Open</NavDropdown.Item>
        <NavDropdown.Item className={getClassName("save")} eventKey="save">Save</NavDropdown.Item>
        <NavDropdown.Item className={getClassName("save_as")} eventKey="save_as">Save As</NavDropdown.Item>
      </NavDropdown>
    </Nav>
    )
}

Note that NavDropdown.Item component needs to accept the className prop and pass it to the actual html tag that needs to have it.

I don't see anything fatally wrong with your example. I would however suggest that you use onClick instead of onSelect for better support.

If you would want to make your example a lot better, I would recommend that you get some sort of CSS-in-JS library: styled-components or emotion.sh. I have more experience with styled-components and would recommend styled-components.

You would be able to just remove the CSS based on React props usings styled-components because it literally just adds styling to a component.

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