When I was just entering the React-Redux world, the concept of hooks seemed daunting. so I have to learn React AND Hooks to know React?
It's easy to get overwhelmed when you're not quite sure if your knowledge of vanilla JS will be enough to understand React and Redux, but Hooks are easier than they seem at first glance.
According to the official documentation,
React's new "hooks" APIs give function components the ability to use local component state, execute side effects, and more.
What this means is that you can now favor using Hooks instead of functions like connect() or mapDispatchToProps(). We are able to do this because we are accessing the state directly, we no longer need aids to do so.
Quick start on hooks
We'll be talking about useSelector() and useDispatch() in order to replace connect(), mapDispatchToProps() and mapStateToProps().
useSelector()
This is the equivalent of mapStateToProps. It takes a pure function as an argument that lets it know which part of the state you want to access.
It's also important to note that we're passing a second argument called shallowEqual. By doing this, we are letting it know that it has to use a shallow equality comparison.
You could also opt-out of adding it but rendering is always going to be more expensive than a quick selector check and returning new references will cause unnecessary re-renders whenever we dispatch any actions.
useDispatch()
This is the better version of mapDispatchToProps. To use it, we first need to invoke useDispatch into a variable and store it. After that, we're free to manually dispatch any redux action we have defined.
Using both of these hooks will discard the need for Redux's connect since we are pulling and dispatching directly.
But how does it look like?
Given this quick snippet of a bookList component, we will transform from the traditional connect into hooks.
Using connect
import React from 'react'; | |
import { connect } from 'react-redux'; | |
import Book from '../components/Book'; | |
import { removeBook } from '../actions'; | |
const filtering = (books, filterRes) => (filterRes === 'All' ? books : books.filter(book => book.category === filterRes)); | |
const BookList = ({ books, filter }) => ( | |
<div> | |
{filtering(books, filter).map(book => ( | |
<div key={book.key}> | |
<Book | |
key={book.key} | |
id={book.key} | |
title={book.title} | |
author={book.author} | |
category={book.category} | |
handleDelete={removeBook(book)} | |
/> | |
</div> | |
))} | |
</div> | |
); | |
const mapStateToProps = state => ({ books: state.books, filter: state.filter }); | |
const mapDispatchToProps = dispatch => ({ removeBook: book => dispatch(removeBook(book)) }); | |
export default connect(mapStateToProps, mapDispatchToProps)(BookList); |
Refactoring using hooks
import React from 'react'; | |
import { useDispatch, useSelector, shallowEqual } from 'react-redux'; | |
import Book from '../components/Book'; | |
import { removeBook } from '../actions'; | |
const filtering = (books, filterRes) => (filterRes === 'All' ? books : books.filter(book => book.category === filterRes)); | |
export default BookList = () => { | |
const books = useSelector(state => state.books, shallowEqual) || []; | |
const filter = useSelector(state => state.filter) || {}; | |
const dispatch = useDispatch(); | |
return ( | |
<div> | |
{filtering(books, filter).map(book => ( | |
<div key={book.key}> | |
<Book | |
key={book.key} | |
id={book.key} | |
title={book.title} | |
author={book.author} | |
category={book.category} | |
handleDelete={dispatch(removeBook(book))} | |
/> | |
</div> | |
))} | |
</div> | |
); | |
}; |
Got something to add? Please feel free to reach out for any question, comment or meme.
Top comments (1)
It saved my day!