Italik
Italik

Reputation: 696

How to add active class/state for li element in ReactJS?

I'm struggling with one issue all day long... I have list of books and after click user can see details of each books. I want to add background-color when element li is clicked (something like an active class). I use Redux and React and have no idea what is the best approach to create this feature. Please, give me some hints because I'm getting discouraged to React environment...

book-list.js

class BookList extends Component {
    renderList(){
        return this.props.books.map((book) => {
            return (
                <li key={book.title} 
                    className="list-group-item" 
                    onClick={() => this.props.selectBook(book)}>
                    {book.title}
                </li>
            )
        })
    }

render () {
    return (
        <div>
            <h3 className="m-t-2 m-b-1">Books to read:</h3>
            <ul className="list-group col-sm-4">
                {this.renderList()}
            </ul>
        </div>
    );
 } 
}

function mapStateToProps (state) {
    return {
        books: state.books
    };
 }

function mapDispatchToProps(dispatch) {
    return bindActionCreators({ selectBook: selectBook }, dispatch)
}

export default connect (mapStateToProps, mapDispatchToProps)(BookList); 

reducer_active_book.js

export default function(state = null, action) {
    switch(action.type) {
    case 'BOOK_SELECTED':
        return action.payload;
    }
        return state;
}

actions.js

export function selectBook (book) {
    return {
        type: 'BOOK_SELECTED',
        payload: book
    }
}

Upvotes: 6

Views: 8779

Answers (3)

user3032310
user3032310

Reputation: 1

In Book List Component

function mapStateToProps(state){

  return {
       books:state.books,
       ActiveBook:state.ActiveBook
  };
}



renderList(){

 console.log(this.props.books);
  return this.props.books.map( (book,idx)=>{

        return <li
         onClick={ ()=>this.props.selectBook(book) }
         className= {"list-group-item  " + ( this.props.ActiveBook ? ( this.props.ActiveBook.title===book.title ? "active" : "") : '') }  key={idx}>{book.title}</li>
   } );
}

I have done correctly using this.

Upvotes: 0

Subin Sebastian
Subin Sebastian

Reputation: 10997

You can use classnames package https://github.com/JedWatson/classnames

import classNames from 'classnames';

return this.props.books.map((book) => {
        return (
            <li key={book.title} 
                className={classnames({'list-group-item':true, 'active': book.active})} 
                onClick={() => this.props.selectBook(book)}>
                {book.title}
            </li>
        )
    })

active class will affect only if book.active is true

//EDIT you have to pass reducer_active_book property from your state through mapStateToProps

function mapStateToProps (state) {
return {
    books: state.books,
    reducer_active_book: state.reducer_active_book,
};

}

Now in render you can use this.

return this.props.books.map((book) => {
        return (
            <li key={book.title} 
                className={classnames({'list-group-item':true, 'active': this.props.reducer_active_book.id === book.id})} 
                onClick={() => this.props.selectBook(book)}>
                {book.title}
            </li>
        )
    })

Upvotes: 3

LMenon
LMenon

Reputation: 66

<li key={book.title} 
    className={"list-group-item " + (book.flag ? 'active-class' : 'inactive-class')}
    onClick={() => this.props.selectBook(book)}>
    {book.title}
</li>

Try setting a 'flag' when one book is selected, and conditionally add style classes(active-class/inactive-class) accordingly

Upvotes: 1

Related Questions