Home > Blockchain >  React tab-like system using CSS classes
React tab-like system using CSS classes

Time:10-08

I have 5 div's and 5 buttons. On each button clicked one div become visible. the other four gets hidden. I just want to ask is there any other better way to do it. Give suggestion as much as possible. Thank you!

let id1 = React.createRef()
  let id2 = React.createRef()
  let id3 = React.createRef()
  let id4 = React.createRef()
  let id5 = React.createRef()

  function iid1() {
    id1.current.classList.remove('hidden')
    id1.current.classList.add('contents')
    id2.current.classList.add('hidden')
    id3.current.classList.add('hidden')
    id4.current.classList.add('hidden')
    id5.current.classList.add('hidden')
  }
  function iid2() {
    id1.current.classList.add('hidden')
    id2.current.classList.remove('hidden')
    id2.current.classList.add('contents')
    id3.current.classList.add('hidden')
    id4.current.classList.add('hidden')
    id5.current.classList.add('hidden')
  }
  function iid3() {
    id1.current.classList.add('hidden')
    id2.current.classList.add('hidden')
    id3.current.classList.remove('hidden')
    id3.current.classList.add('contents')
    id4.current.classList.add('hidden')
    id5.current.classList.add('hidden')
  }
  function iid4() {
    id1.current.classList.add('hidden')
    id2.current.classList.add('hidden')
    id3.current.classList.add('hidden')
    id4.current.classList.remove('hidden')
    id4.current.classList.add('contents')
    id5.current.classList.add('hidden')
  }
  function iid5() {
    id1.current.classList.add('hidden')
    id2.current.classList.add('hidden')
    id3.current.classList.add('hidden')
    id4.current.classList.add('hidden')
    id5.current.classList.remove('hidden')
    id5.current.classList.add('contents')
  }

I just want the above code to be more efficient & readable. I'm looking for best practices for javascript. You can also tell me you would you solve this problem. I'm not looking for answer's. I'm here to seek best practices, Thank you.

CodePudding user response:

Use state to identify which div is the selected one. Buttons will change the state and your app will re-render adjusting the classNames for the divs.

const App = () => {
  
  const [selected,setSelected] = React.useState(0);
  const DIV_IDS = [0,1,2,3,4,5];
  
  const selectItems = DIV_IDS.map((item) => {
    return(
      <button onClick={() => setSelected(item)}>{item}</button>
    );
  });
  
  const divItems = DIV_IDS.map((item) => {
    return (
      <div key={item} className={selected === item ? 'visible' : 'hidden'}>
        I am div {item}
      </div>
    );
  });

  return(
    <div>
      <div>{selectItems}</div>
      <div>{divItems}</div>
    </div>
  );
};

ReactDOM.render(<App/>, document.getElementById('root'));
.hidden {
  visibility: hidden;
}

.visible {
  visibility: visible;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.3/umd/react-dom.production.min.js"></script>
<div id="root"></div>

CodePudding user response:

May be best to just have the class in your JSX element classes. Something like:

<element className={(condition_for_shown) ? 'contents' : 'hidden'}>
...
</element>

and then for each button would be:

<button type="button" onClick={() => setStateConditonToSomething}>
...
</button>

Note that you'll need to store the condition in react state with useState or however you wanna store it.

CodePudding user response:

The way i'd do it is -


const DivHidingComponent = ({ elementCount = 5 }) => { // element count defaults to 5
    const [visibilityIndex, setVisibilityIndex] = useState(0);

    const onClickCallback = useCallback((index) => () => {
      setVisibilityIndex(index);
    })
     
    const buttonGroup = useMemo(() => {
        const buttonGroup = [];
        for (let i = 0; i < elementCount; i  ) {
           buttonGroup.push(
                <button key={`${i}-button`} onClick={onClickCallback(i)} />
           )
        }
        return buttonGroup;
    },  [elementCount])

    // only re-runs on a button click
    const divGroup = useMemo(() => {
        const divGroup = [];
        for (let i = 0; i < elementCount; i  ) {
           divGroup.push(
                <div key={`${i}-div`} style={{ visibility: visibilityIndex === i ? 'visible' : 'hidden'  }} />
           );
        }
        return divGroup;
    },  [visibilityIndex]);

    
    return (
        <div>
          <div>
             {buttonGroup}
          </div>
          <div>
             {divGroup}
          </div>
        </div>
   );
}

I set the style directly in the div group loop, but you could assign a class name or go about setting the style however you want.

Div's visibility is set by the visibility index that is driven by the buttons being clicked on.

I passed the elementCount variable in the props so you could scale this to however many elements you want. 5 or a 1000. I assigned elementCount a value of 5 that will act as a default for when no value is passed when the component is initialized.

Also, you could drop the useMemo and useCallback hooks and it would still execute fine. But it would help improve performance if you say, set the element count to 10,000. With those hooks in place it'd only re-build the div group on re-render. That'd be the difference between running the loops 20k times (10k for buttons, 10k for divs).

I added the last paragraph incase you were not aware of React Hooks!

I hope this helps!

  • Related