Search code examples
javascriptreactjscomponentsuse-state

React: How to set a component in 'active' state one at a time, and remove 'active' from all other component on click?


I want to set a particular component as active on click, and update the active component when some other component is clicked. Currently, both the components are remaining in active state. I want to remove active state from previously clicked component.

 const [activeComponent, setActiveComponent] = useState(null);

  const updateActiveComponent = (e, active_component) => {
    if (active_component.id != activeComponent?.id) {
      setActiveComponent(active_component);
    } else {
      closeActiveComponent();
    }
  };
  const closeActiveComponent = () => {
    setActiveComponent(null);
  };
<MyComponent
        key={index}
        card={card}
        clickHandler={updateActiveComponent}
      />

Solution

  • To make it general, let's imagine that you have not just two components, but any number of components.

    We have 2 cases:

    1. Components work as a radio buttons. Only one component at a time can be active.
    2. Components work as a checkbox buttons. Multiple components can be at active state.

    As I understood, you have the first case. So, to make it working we need to store the id of active component.

    import { useState } from 'react'
    
    const Component = ({ isActive, onClick }) => {
        return <div onClick={onClick}> {isActive ? 'Active' : 'Not active'} </div>
    }
    
    const Page = () = {
        // -1 means that we have not set any component to the active state
        const [activeElement, setActiveElement] = useState(-1);
    
        const updateActiveElement = (id) => {
            setActiveElement(activeElement !== id ? id : -1);
        }
    
        return (
            <div>
                <Component active={0 === activeElement} onClick={() => updateActiveElement(0)} />
                <Component active={1 === activeElement} onClick={() => updateActiveElement(1)} />
            </div>
        );
    }
    

    For a checkbox type case, we need to store the state of each component individually, means, we need to create the array of each components state.

    import { useState } from 'react'
    
    const Component = ({ isActive, onClick }) => {
        return <div onClick={onClick}> {isActive ? 'Active' : 'Not active'} </div>
    }
    
    const Page = ({ amountComponents }) = {
        const [elementStates, setElementStates] = useState(Array(amountComponents).fill(false));
    
        const updateActiveElement = (id) => {
            setActiveElement(elementStates.map((isActive, index) => index === id ? !isActive : isActive ));
        }
    
        return (
            <div>
                {elementStates.map((isActive, id) => (
                    <Component active={isActive} onClick={() => updateActiveElement(id)} />
                )}
            </div>
        );
    }