1

I have a List and Grid type display. How do I toggle between them in React. I want to toggle between jsGridView and jsListView classes.

This is the vanilla js of the toggling of classes

  const listView = document.querySelector('.list-view');
  const gridView = document.querySelector('.grid-view');
  const projectsList = document.querySelector('.project-boxes');
  
  listView.addEventListener('click', () => {
    gridView.classList.remove('active');
    listView.classList.add('active');
    projectsList.classList.remove('jsGridView');
    projectsList.classList.add('jsListView');
  });
  
  gridView.addEventListener('click', () => {
    gridView.classList.add('active');
    listView.classList.remove('active');
    projectsList.classList.remove('jsListView');
    projectsList.classList.add('jsGridView');
  });

** this is my react file where I have the display items and buttons to toggle. how do I implement the toggle event listeners into my react file** How do I toggle between the two classes - jsGridVew and jsListView

const [isActive, setIsActive] = useState(false)

    const listToggle = () => {
     setIsActive(!isActive)
    }

   <button key={isActive} className="view-btn list-view" title="List View" onClick={listToggle}>
        <i className="fal fa-list-ul fa-2x"></i>
    </button>

    <button className="view-btn grid-view active" title="Grid View">
        <i className="fal fa-th-large fa-2x"></i>
     </button>

     <div className="project-boxes jsGridView">
        {!loading && records.length === 0 ? (<h4 style={{ margin: '20px' }} className='center'>No 
           records, sorry</h4>) : records.map((record, key) => (
             <RecordItem key={key} record={record} isFilter={isFilter} filterByWhat={filterByWhat} />
           ))}
      </div>

EDIT: > I also want to add an 'active class on each button on click. I've tried somethings but it doesn't work

3 Answers 3

1

I am assuming this div is where you want to toggle between jsGridView and jsListView

<div className="project-boxes jsGridView">

So why not use a state variable to store the class name? Then use the onClick even to set it.

const [cName, setClassName] = useState('jsGridView');

return (
<Fragment>
   <button className="view-btn list-view" title="List View" onClick={() => setClassName('jsListView')}>
        List View
    </button>
   <button className="view-btn list-view" title="Grid View" onClick={() => setClassName('jsGridView')}>
        Grid View
     </button>


     <div className={"project-boxes "+cName}>
        {!loading && records.length === 0 ? (<h4 style={{ margin: '20px' }} className='center'>No 
           records, sorry</h4>) : records.map((record, key) => (
             <RecordItem key={key} record={record} isFilter={isFilter} filterByWhat={filterByWhat} />
           ))}
      </div>
</Fragment>
)

So here you set your class to jsGridView initially so it renders in grid view by default. But you also have 2 buttons that can flip it between grid and list view.

You can also add an active class to the button if you want.

   <button className={"view-btn list-view"+(cName === 'jsListView' ? ' active_btn':'')} title="List View" onClick={() => setClassName('jsListView')}>
        List View
    </button>
   <button className={"view-btn list-view"+(cName === 'jsGridView' ? ' active_btn':'')} title="Grid View" onClick={() => setClassName('jsGridView')}>
        Grid View
     </button>

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

Comments

0

If one class is on, and the other is off, you can do

function toggleClass(elem) {
  const classList = elem.classList;
  classList.toggle('class1');
  classList.toggle('class2');
}

Now the on/off status of the two classes is reversed

Also, in your Styles / CSS file, you can add :not on one class and then not need to use the other class, like

#elem.class1 {
  color: ...;
  font-size: ...;
}

#elem.class2, #elem:not(.class1) {
  color: ...;
  font-size: ...;
}

So that :not(.class1) has the same styling effects as adding class2

Comments

0

In React, it's uncommon to mix "vanilla" imperative JS and React like this. React provides a clean solution for toggling displayed elements that I would advise you use instead.

Take the following as an example:

// list-view.jsx
const ListView = ({ items=[] }) => {

  const itemsElements = items.map(item => {
    return (<li>{item}</li>)
  });
  
  return (<ul>{itemsElements}</ul>)
}

// grid-view.jsx
const GridView = ({ items=[] }) => {

  const itemsElements = items.map(item => {
    return (<span>{item} </span>)
  });
  
  return (<div>{itemsElements}</div>)
}

// list-grid-view.jsx
const ListGridView = ({ items=[] }) => {
  const [listView, setListView] = React.useState(true);
  
  // this fn toggles the listView variable
  const toggleListView = React.useCallback(() => {
    setListView(!listView);
  }, [listView, setListView]);
  
  return (
    <div>
      <button onClick={toggleListView} >Toggle!</button>
      {listView ? <ListView items={items} /> : <GridView items={items} />}
    </div>
  );
}

const items = ['Hello', 'World', '!'];
const element = <ListGridView items={items} />

ReactDOM.render(element, document.getElementById('root'));
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.8.0/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.8.0/umd/react-dom.production.min.js"></script>
<div id="root"></div>

Comments

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.