1671544260
In this Redux Toolkit article, we will learn about How to Build a Simple Redux Store with Redux Toolkit. Setting up even a simple Redux store used to be hard. Not anymore. With the help of Redux Toolkit we can create Redux stores much faster and with less code. This tutorial will help you learn how to use Redux Toolkit to create such a simple store and how to implement it in your React app.
In this tutorial we will take a look at how to create a simple redux store with Redux Toolkit. The app we will be working on will be an app for creating books collection. It will allow users to add books to collections and remove them. It will also show all books currently in collection.
The main app state for book collection will be the Redux state. Adding and removing books will be handled by reducer functions. We will create this app with the create-react-app. This will give us what we need to get the React app up and running. For Redux, we will need two additional dependencies.
The first dependency will be react-redux, version 7.2.6. This library contains official React bindings for Redux. Second dependency we will need is @reduxjs/toolkit, version v1.6.2. This library contains tools that make working with Redux much easier. This also includes setting up a redux store.
This tutorial will also use uuid library, version 8.3.2. This library is not necessary for the Redux state. We will use it to generate unique ids for added books. These ids will make it easier to remove specific book from collection. This is all we need to get started.
Let’s start with the most interesting part, creating the Redux store. To keep the project tidy, all store-related stuff will be in /store
directory, right inside /src
. The /store
directory will contain two files: books.js
and index.js
. The books.js
will contain Redux state slice for book collection.
The index.js
will contain a very simple setup for the Redux store for our React app.
The first part of the redux state is will be the redux state slice. We will create the redux slice with createSlice()
, a method provided by @reduxjs/toolkit
. This method allows us to do a couple of things. First, it allows us to define the initial state for our store, the book collection.
It also allows us to define reducer functions for the same store. We will use these reducers later to add books to collection and also to remove them. The initial state for the store will be an object with single property, books
. The value of this property will be an empty array.
For this tutorial we will need two reducers. One will be for adding new book to the Redux store. The second will be removing book from the store. We can call these reducers addBook
and removeBook
. We will define these reducers in an object we will use as a value for reducers
property of createSlice()
method.
The last thing for the createSlice()
method is adding name
property with some name for the store. This is used by Redux toolkit to generate required actions for our Redux store. When we have this setup, the createSlice()
method will automatically generate two things: actions and reducer for our new slice.
It used to be that we had to create these two by ourselves. This is no longer necessary thanks to the Redux toolkit and the whole process is much easier, as you can see. Now, we just have to export those actions and the reducer and we are done here.
// src/store/books.js
// Import createSlice() from Redux toolkit:
import { createSlice } from '@reduxjs/toolkit'
// Initial state for Redux store:
const initialState = {
books: [],
}
// Create Redux state slice
const booksSlice = createSlice({
name: 'books',
initialState, // Define initial state
reducers: {
// Define reducers
addBook: (state, action) => {
// Reducer for adding new book to collection
// Create new state by taking existing books
// and combining them with newly added book:
state.books = [...state.books, action.payload]
},
removeBook: (state, action) => {
// Reducer for removing book from collection
// Filter out a book that matches provided "id":
state.books = state.books.filter((b) => b.id !== action.payload.id)
},
},
})
// Export actions generated by "createSlice()":
export const { addBook, removeBook } = booksSlice.actions
// Export reducer generated by "createSlice()":
export default booksSlice.reducer
We have the setup for Redux state slice, but there is a bit more we have to do. We have to create the Redux store itself and connect it to the reducer generated for our books slice. We will do this by using another method provided by Redux toolkit called configureStore()
.
This method accepts one parameter, configuration object for the Redux store. Right now, we need to define only one property of this object, reducer
. The value of this property will be an object with the reducer we want to use. This will be the booksSlice.reducer
we recently worked with in books.js
.
We have to import this reducer and add it to the reducer
object in store config. After that, we are done as well.
// src/store/index.js
// Import configureStore() from Redux toolkit:
import { configureStore } from '@reduxjs/toolkit'
// Import books reducer:
import booksReducer from './books'
// Create Redux store:
export const store = configureStore({
reducer: {
booksReducer, // Add books reducer
},
})
Both, Redux slice and store are ready. There is one last step we have to make. We have to create Redux provider and connect it with the store we just finished. This will be very fast. We have to go to the main file that renders the main React App
component. This will probably be index.js
in src/
.
Here, we have to import Provider
component from react-redux
library and our Redux store, we exported from src/store/index.js
. We will add the Provider
component to the component tree and set our store as a value for Provider’s store
prop. This will make the store available for the whole app.
// src/index.jsx
// Import React deps:
import { StrictMode } from 'react'
import ReactDOM from 'react-dom'
// Import Redux provider:
import { Provider } from 'react-redux'
// Import some styles:
import './styles.css'
// Import redux store:
import { store } from './store'
// Import main App component:
import { App } from './App'
// Render the React app:
const rootElement = document.getElementById('root')
ReactDOM.render(
<StrictMode>
{/* Add Redux provider */}
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
rootElement
)
The first component for our books collection app will be form for adding books. This component will have its own local state (useState), for storing information about book’s title and author. We will store these data in Redux store using dispatch()
method returned from useDispatch()
hook that is provided by react-redux
.
To add new book, we use the addBook
reducer we exported from src/store/books.js
. We will pass this reducer to the dispatch()
method. Payload for the addBook
reducer will be data for the book: title, author and unique id generated by uuid
. After new book is added, we will reset local state for title and author.
// src/Form.jsx
// Import dependencies:
import { memo, useCallback, useState } from 'react'
import { useDispatch } from 'react-redux'
import { v4 as uuidV4 } from 'uuid'
// Import addBook reducer:
import { addBook } from './store/books'
// Create Form component:
export const Form = memo(() => {
// Prepare Redux dispatch method:
const dispatch = useDispatch()
// Create form states:
const [bookTitle, setBookTitle] = useState('')
const [bookAuthor, setBookAuthor] = useState('')
// Add form onSubmit handler:
const onFormSubmit = useCallback(
(event) => {
event.preventDefault()
// Dispatch addBook reducer with payload
// containing data for new book:
dispatch(
addBook({
bookTitle,
bookAuthor,
id: uuidV4(),
})
)
// Reset form states:
setBookTitle('')
setBookAuthor('')
},
[bookAuthor, bookTitle, dispatch]
)
return (
<form onSubmit={onFormSubmit}>
<fieldset>
<label htmlFor="title">Book title</label>
<input
type="text"
id="title"
value={bookTitle}
onChange={(event) => setBookTitle(event.target.value)}
/>
</fieldset>
<fieldset>
<label htmlFor="author">Book author</label>
<input
type="text"
id="author"
value={bookAuthor}
onChange={(event) => setBookAuthor(event.target.value)}
/>
</fieldset>
<fieldset>
<button type="submit">Add book</button>
</fieldset>
</form>
)
})
Thanks to the form, we can store books in our Redux store. Next thing we can do is create some list showing all books that are currently in the store. We can also add some button to remove specific book from the list, and the store. To do this, we will have to do a couple of things.
First, we will again have to use the useDispatch()
hook to get the dispatch()
method so we can update our store. Now, the reducer we will dispatch will be the removeBook
. We will import this reducer from src/store/books.js
. We will handle removing books with new handler function called onBookRemove()
.
This function will accept one parameter: bookId
. It will pass this id as a payload to the removeBook
reducer, and pass this reducer to the dispatch()
method. The payload will be an object with id
property and id of the book we want to remove. In order to list the books in store, we will need to get them somehow.
We can get those books by using the useSelector()
hook, also provided by react-redux
. This hook allows us to access the redux store’s state, the books state in our case. All we need is to provide this hook with a selector function to get the data we want.
The hook passes state
as an argument to the selector function. We will use this argument to get the booksReducer
we registered when we configured the Redux store (in src/store/index.js
). This reducer contains the slice we created for our books collection. The name of this slice is books
.
We defined this name in src/store/books.js
. It is the name
property in createSlice()
method. We will now use this name to access the books slice. The state of this slice is the array for our books collection. When we have this, we can use map()
to iterate over the books array to generate and display a list of all books in collection.
// src/BookList.jsx
// Import dependencies:
import { memo, useCallback } from 'react'
import { useDispatch, useSelector } from 'react-redux'
// Import removeBook reducer:
import { removeBook } from './store/books'
// Create BooksList component:
export const BooksList = memo(() => {
// Get books from Redux store:
const books = useSelector((state) => state.booksReducer.books)
// Prepare dispatch method:
const dispatch = useDispatch()
// Create handler for removing book:
const onBookRemove = useCallback(
(bookId) => {
dispatch(removeBook({ id: bookId }))
},
[dispatch]
)
return (
<div className="booklist">
{books.map((book) => (
<div key={book.bookTitle} className="book">
{`${book.bookTitle} by ${book.bookAuthor}`}
<button
className="removeButton"
onClick={() => onBookRemove(book.id)}
>
×
</button>
</div>
))}
</div>
)
})
Redux, form and book list components are ready. We can now put these components together in the App
component. Along with this, we can also add a heading showing how many books we have in our collection. We will get this number by using the useSelector
hook to get the books state.
In this case, instead of asking for state.booksReducer.books
we can ask directly for the number of books in the state. We can do this by adding the length
property: state.booksReducer.books.length
. This will return the number of books in the store instead of the array itself.
// src/App.jsx
// Import dependencies:
import { memo } from 'react'
import { useSelector } from 'react-redux'
// Import components:
import { BooksList } from './BooksList'
import { Form } from './Form'
// Create App component:
export const App = memo(() => {
// Get books from Redux store:
const booksCount = useSelector((state) => state.booksReducer.books.length)
return (
<div className="app">
<h1>Books in collection: {booksCount}</h1>
<Form />
{booksCount > 0 && <BooksList />}
</div>
)
})
The index.jsx
where we added the Redux Provider
component stayed the same. No change is necessary here.
// src/index.jsx
// Import React deps:
import { StrictMode } from 'react'
import ReactDOM from 'react-dom'
// Import Redux provider:
import { Provider } from 'react-redux'
// Import some styles:
import './styles.css'
// Import redux store:
import { store } from './store'
// Import main App component:
import { App } from './App'
// Render the React app:
const rootElement = document.getElementById('root')
ReactDOM.render(
<StrictMode>
{/* Add Redux provider */}
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
rootElement
)
The whole flow of setting up even a simple Redux store used to be tedious and lengthy. Developers had to write a lot of code to just get started. This is no longer the case thanks to Redux toolkit. I hope that this tutorial helped you learn how to create a simple Redux store and how to implement it in your React app.
Demo on Codesandbox.
Original article sourced at: https://blog.alexdevero.com
1671544260
In this Redux Toolkit article, we will learn about How to Build a Simple Redux Store with Redux Toolkit. Setting up even a simple Redux store used to be hard. Not anymore. With the help of Redux Toolkit we can create Redux stores much faster and with less code. This tutorial will help you learn how to use Redux Toolkit to create such a simple store and how to implement it in your React app.
In this tutorial we will take a look at how to create a simple redux store with Redux Toolkit. The app we will be working on will be an app for creating books collection. It will allow users to add books to collections and remove them. It will also show all books currently in collection.
The main app state for book collection will be the Redux state. Adding and removing books will be handled by reducer functions. We will create this app with the create-react-app. This will give us what we need to get the React app up and running. For Redux, we will need two additional dependencies.
The first dependency will be react-redux, version 7.2.6. This library contains official React bindings for Redux. Second dependency we will need is @reduxjs/toolkit, version v1.6.2. This library contains tools that make working with Redux much easier. This also includes setting up a redux store.
This tutorial will also use uuid library, version 8.3.2. This library is not necessary for the Redux state. We will use it to generate unique ids for added books. These ids will make it easier to remove specific book from collection. This is all we need to get started.
Let’s start with the most interesting part, creating the Redux store. To keep the project tidy, all store-related stuff will be in /store
directory, right inside /src
. The /store
directory will contain two files: books.js
and index.js
. The books.js
will contain Redux state slice for book collection.
The index.js
will contain a very simple setup for the Redux store for our React app.
The first part of the redux state is will be the redux state slice. We will create the redux slice with createSlice()
, a method provided by @reduxjs/toolkit
. This method allows us to do a couple of things. First, it allows us to define the initial state for our store, the book collection.
It also allows us to define reducer functions for the same store. We will use these reducers later to add books to collection and also to remove them. The initial state for the store will be an object with single property, books
. The value of this property will be an empty array.
For this tutorial we will need two reducers. One will be for adding new book to the Redux store. The second will be removing book from the store. We can call these reducers addBook
and removeBook
. We will define these reducers in an object we will use as a value for reducers
property of createSlice()
method.
The last thing for the createSlice()
method is adding name
property with some name for the store. This is used by Redux toolkit to generate required actions for our Redux store. When we have this setup, the createSlice()
method will automatically generate two things: actions and reducer for our new slice.
It used to be that we had to create these two by ourselves. This is no longer necessary thanks to the Redux toolkit and the whole process is much easier, as you can see. Now, we just have to export those actions and the reducer and we are done here.
// src/store/books.js
// Import createSlice() from Redux toolkit:
import { createSlice } from '@reduxjs/toolkit'
// Initial state for Redux store:
const initialState = {
books: [],
}
// Create Redux state slice
const booksSlice = createSlice({
name: 'books',
initialState, // Define initial state
reducers: {
// Define reducers
addBook: (state, action) => {
// Reducer for adding new book to collection
// Create new state by taking existing books
// and combining them with newly added book:
state.books = [...state.books, action.payload]
},
removeBook: (state, action) => {
// Reducer for removing book from collection
// Filter out a book that matches provided "id":
state.books = state.books.filter((b) => b.id !== action.payload.id)
},
},
})
// Export actions generated by "createSlice()":
export const { addBook, removeBook } = booksSlice.actions
// Export reducer generated by "createSlice()":
export default booksSlice.reducer
We have the setup for Redux state slice, but there is a bit more we have to do. We have to create the Redux store itself and connect it to the reducer generated for our books slice. We will do this by using another method provided by Redux toolkit called configureStore()
.
This method accepts one parameter, configuration object for the Redux store. Right now, we need to define only one property of this object, reducer
. The value of this property will be an object with the reducer we want to use. This will be the booksSlice.reducer
we recently worked with in books.js
.
We have to import this reducer and add it to the reducer
object in store config. After that, we are done as well.
// src/store/index.js
// Import configureStore() from Redux toolkit:
import { configureStore } from '@reduxjs/toolkit'
// Import books reducer:
import booksReducer from './books'
// Create Redux store:
export const store = configureStore({
reducer: {
booksReducer, // Add books reducer
},
})
Both, Redux slice and store are ready. There is one last step we have to make. We have to create Redux provider and connect it with the store we just finished. This will be very fast. We have to go to the main file that renders the main React App
component. This will probably be index.js
in src/
.
Here, we have to import Provider
component from react-redux
library and our Redux store, we exported from src/store/index.js
. We will add the Provider
component to the component tree and set our store as a value for Provider’s store
prop. This will make the store available for the whole app.
// src/index.jsx
// Import React deps:
import { StrictMode } from 'react'
import ReactDOM from 'react-dom'
// Import Redux provider:
import { Provider } from 'react-redux'
// Import some styles:
import './styles.css'
// Import redux store:
import { store } from './store'
// Import main App component:
import { App } from './App'
// Render the React app:
const rootElement = document.getElementById('root')
ReactDOM.render(
<StrictMode>
{/* Add Redux provider */}
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
rootElement
)
The first component for our books collection app will be form for adding books. This component will have its own local state (useState), for storing information about book’s title and author. We will store these data in Redux store using dispatch()
method returned from useDispatch()
hook that is provided by react-redux
.
To add new book, we use the addBook
reducer we exported from src/store/books.js
. We will pass this reducer to the dispatch()
method. Payload for the addBook
reducer will be data for the book: title, author and unique id generated by uuid
. After new book is added, we will reset local state for title and author.
// src/Form.jsx
// Import dependencies:
import { memo, useCallback, useState } from 'react'
import { useDispatch } from 'react-redux'
import { v4 as uuidV4 } from 'uuid'
// Import addBook reducer:
import { addBook } from './store/books'
// Create Form component:
export const Form = memo(() => {
// Prepare Redux dispatch method:
const dispatch = useDispatch()
// Create form states:
const [bookTitle, setBookTitle] = useState('')
const [bookAuthor, setBookAuthor] = useState('')
// Add form onSubmit handler:
const onFormSubmit = useCallback(
(event) => {
event.preventDefault()
// Dispatch addBook reducer with payload
// containing data for new book:
dispatch(
addBook({
bookTitle,
bookAuthor,
id: uuidV4(),
})
)
// Reset form states:
setBookTitle('')
setBookAuthor('')
},
[bookAuthor, bookTitle, dispatch]
)
return (
<form onSubmit={onFormSubmit}>
<fieldset>
<label htmlFor="title">Book title</label>
<input
type="text"
id="title"
value={bookTitle}
onChange={(event) => setBookTitle(event.target.value)}
/>
</fieldset>
<fieldset>
<label htmlFor="author">Book author</label>
<input
type="text"
id="author"
value={bookAuthor}
onChange={(event) => setBookAuthor(event.target.value)}
/>
</fieldset>
<fieldset>
<button type="submit">Add book</button>
</fieldset>
</form>
)
})
Thanks to the form, we can store books in our Redux store. Next thing we can do is create some list showing all books that are currently in the store. We can also add some button to remove specific book from the list, and the store. To do this, we will have to do a couple of things.
First, we will again have to use the useDispatch()
hook to get the dispatch()
method so we can update our store. Now, the reducer we will dispatch will be the removeBook
. We will import this reducer from src/store/books.js
. We will handle removing books with new handler function called onBookRemove()
.
This function will accept one parameter: bookId
. It will pass this id as a payload to the removeBook
reducer, and pass this reducer to the dispatch()
method. The payload will be an object with id
property and id of the book we want to remove. In order to list the books in store, we will need to get them somehow.
We can get those books by using the useSelector()
hook, also provided by react-redux
. This hook allows us to access the redux store’s state, the books state in our case. All we need is to provide this hook with a selector function to get the data we want.
The hook passes state
as an argument to the selector function. We will use this argument to get the booksReducer
we registered when we configured the Redux store (in src/store/index.js
). This reducer contains the slice we created for our books collection. The name of this slice is books
.
We defined this name in src/store/books.js
. It is the name
property in createSlice()
method. We will now use this name to access the books slice. The state of this slice is the array for our books collection. When we have this, we can use map()
to iterate over the books array to generate and display a list of all books in collection.
// src/BookList.jsx
// Import dependencies:
import { memo, useCallback } from 'react'
import { useDispatch, useSelector } from 'react-redux'
// Import removeBook reducer:
import { removeBook } from './store/books'
// Create BooksList component:
export const BooksList = memo(() => {
// Get books from Redux store:
const books = useSelector((state) => state.booksReducer.books)
// Prepare dispatch method:
const dispatch = useDispatch()
// Create handler for removing book:
const onBookRemove = useCallback(
(bookId) => {
dispatch(removeBook({ id: bookId }))
},
[dispatch]
)
return (
<div className="booklist">
{books.map((book) => (
<div key={book.bookTitle} className="book">
{`${book.bookTitle} by ${book.bookAuthor}`}
<button
className="removeButton"
onClick={() => onBookRemove(book.id)}
>
×
</button>
</div>
))}
</div>
)
})
Redux, form and book list components are ready. We can now put these components together in the App
component. Along with this, we can also add a heading showing how many books we have in our collection. We will get this number by using the useSelector
hook to get the books state.
In this case, instead of asking for state.booksReducer.books
we can ask directly for the number of books in the state. We can do this by adding the length
property: state.booksReducer.books.length
. This will return the number of books in the store instead of the array itself.
// src/App.jsx
// Import dependencies:
import { memo } from 'react'
import { useSelector } from 'react-redux'
// Import components:
import { BooksList } from './BooksList'
import { Form } from './Form'
// Create App component:
export const App = memo(() => {
// Get books from Redux store:
const booksCount = useSelector((state) => state.booksReducer.books.length)
return (
<div className="app">
<h1>Books in collection: {booksCount}</h1>
<Form />
{booksCount > 0 && <BooksList />}
</div>
)
})
The index.jsx
where we added the Redux Provider
component stayed the same. No change is necessary here.
// src/index.jsx
// Import React deps:
import { StrictMode } from 'react'
import ReactDOM from 'react-dom'
// Import Redux provider:
import { Provider } from 'react-redux'
// Import some styles:
import './styles.css'
// Import redux store:
import { store } from './store'
// Import main App component:
import { App } from './App'
// Render the React app:
const rootElement = document.getElementById('root')
ReactDOM.render(
<StrictMode>
{/* Add Redux provider */}
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
rootElement
)
The whole flow of setting up even a simple Redux store used to be tedious and lengthy. Developers had to write a lot of code to just get started. This is no longer the case thanks to Redux toolkit. I hope that this tutorial helped you learn how to create a simple Redux store and how to implement it in your React app.
Demo on Codesandbox.
Original article sourced at: https://blog.alexdevero.com
1671650280
In this Redux Toolkit article, we will learn about How to Build A Simple Redux Store with Redux Toolkit. Setting up even a simple Redux store used to be hard. Not anymore. With the help of Redux Toolkit we can create Redux stores much faster and with less code. This tutorial will help you learn how to use Redux Toolkit to create such a simple store and how to implement it in your React app.
In this tutorial we will take a look at how to create a simple redux store with Redux Toolkit. The app we will be working on will be an app for creating books collection. It will allow users to add books to collections and remove them. It will also show all books currently in collection.
The main app state for book collection will be the Redux state. Adding and removing books will be handled by reducer functions. We will create this app with the create-react-app. This will give us what we need to get the React app up and running. For Redux, we will need two additional dependencies.
The first dependency will be react-redux, version 7.2.6. This library contains official React bindings for Redux. Second dependency we will need is @reduxjs/toolkit, version v1.6.2. This library contains tools that make working with Redux much easier. This also includes setting up a redux store.
This tutorial will also use uuid library, version 8.3.2. This library is not necessary for the Redux state. We will use it to generate unique ids for added books. These ids will make it easier to remove specific book from collection. This is all we need to get started.
Let’s start with the most interesting part, creating the Redux store. To keep the project tidy, all store-related stuff will be in /store
directory, right inside /src
. The /store
directory will contain two files: books.js
and index.js
. The books.js
will contain Redux state slice for book collection.
The index.js
will contain a very simple setup for the Redux store for our React app.
The first part of the redux state is will be the redux state slice. We will create the redux slice with createSlice()
, a method provided by @reduxjs/toolkit
. This method allows us to do a couple of things. First, it allows us to define the initial state for our store, the book collection.
It also allows us to define reducer functions for the same store. We will use these reducers later to add books to collection and also to remove them. The initial state for the store will be an object with single property, books
. The value of this property will be an empty array.
For this tutorial we will need two reducers. One will be for adding new book to the Redux store. The second will be removing book from the store. We can call these reducers addBook
and removeBook
. We will define these reducers in an object we will use as a value for reducers
property of createSlice()
method.
The last thing for the createSlice()
method is adding name
property with some name for the store. This is used by Redux toolkit to generate required actions for our Redux store. When we have this setup, the createSlice()
method will automatically generate two things: actions and reducer for our new slice.
It used to be that we had to create these two by ourselves. This is no longer necessary thanks to the Redux toolkit and the whole process is much easier, as you can see. Now, we just have to export those actions and the reducer and we are done here.
// src/store/books.js
// Import createSlice() from Redux toolkit:
import { createSlice } from '@reduxjs/toolkit'
// Initial state for Redux store:
const initialState = {
books: [],
}
// Create Redux state slice
const booksSlice = createSlice({
name: 'books',
initialState, // Define initial state
reducers: {
// Define reducers
addBook: (state, action) => {
// Reducer for adding new book to collection
// Create new state by taking existing books
// and combining them with newly added book:
state.books = [...state.books, action.payload]
},
removeBook: (state, action) => {
// Reducer for removing book from collection
// Filter out a book that matches provided "id":
state.books = state.books.filter((b) => b.id !== action.payload.id)
},
},
})
// Export actions generated by "createSlice()":
export const { addBook, removeBook } = booksSlice.actions
// Export reducer generated by "createSlice()":
export default booksSlice.reducer
We have the setup for Redux state slice, but there is a bit more we have to do. We have to create the Redux store itself and connect it to the reducer generated for our books slice. We will do this by using another method provided by Redux toolkit called configureStore()
.
This method accepts one parameter, configuration object for the Redux store. Right now, we need to define only one property of this object, reducer
. The value of this property will be an object with the reducer we want to use. This will be the booksSlice.reducer
we recently worked with in books.js
.
We have to import this reducer and add it to the reducer
object in store config. After that, we are done as well.
// src/store/index.js
// Import configureStore() from Redux toolkit:
import { configureStore } from '@reduxjs/toolkit'
// Import books reducer:
import booksReducer from './books'
// Create Redux store:
export const store = configureStore({
reducer: {
booksReducer, // Add books reducer
},
})
Both, Redux slice and store are ready. There is one last step we have to make. We have to create Redux provider and connect it with the store we just finished. This will be very fast. We have to go to the main file that renders the main React App
component. This will probably be index.js
in src/
.
Here, we have to import Provider
component from react-redux
library and our Redux store, we exported from src/store/index.js
. We will add the Provider
component to the component tree and set our store as a value for Provider’s store
prop. This will make the store available for the whole app.
// src/index.jsx
// Import React deps:
import { StrictMode } from 'react'
import ReactDOM from 'react-dom'
// Import Redux provider:
import { Provider } from 'react-redux'
// Import some styles:
import './styles.css'
// Import redux store:
import { store } from './store'
// Import main App component:
import { App } from './App'
// Render the React app:
const rootElement = document.getElementById('root')
ReactDOM.render(
<StrictMode>
{/* Add Redux provider */}
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
rootElement
)
The first component for our books collection app will be form for adding books. This component will have its own local state (useState), for storing information about book’s title and author. We will store these data in Redux store using dispatch()
method returned from useDispatch()
hook that is provided by react-redux
.
To add new book, we use the addBook
reducer we exported from src/store/books.js
. We will pass this reducer to the dispatch()
method. Payload for the addBook
reducer will be data for the book: title, author and unique id generated by uuid
. After new book is added, we will reset local state for title and author.
// src/Form.jsx
// Import dependencies:
import { memo, useCallback, useState } from 'react'
import { useDispatch } from 'react-redux'
import { v4 as uuidV4 } from 'uuid'
// Import addBook reducer:
import { addBook } from './store/books'
// Create Form component:
export const Form = memo(() => {
// Prepare Redux dispatch method:
const dispatch = useDispatch()
// Create form states:
const [bookTitle, setBookTitle] = useState('')
const [bookAuthor, setBookAuthor] = useState('')
// Add form onSubmit handler:
const onFormSubmit = useCallback(
(event) => {
event.preventDefault()
// Dispatch addBook reducer with payload
// containing data for new book:
dispatch(
addBook({
bookTitle,
bookAuthor,
id: uuidV4(),
})
)
// Reset form states:
setBookTitle('')
setBookAuthor('')
},
[bookAuthor, bookTitle, dispatch]
)
return (
<form onSubmit={onFormSubmit}>
<fieldset>
<label htmlFor="title">Book title</label>
<input
type="text"
id="title"
value={bookTitle}
onChange={(event) => setBookTitle(event.target.value)}
/>
</fieldset>
<fieldset>
<label htmlFor="author">Book author</label>
<input
type="text"
id="author"
value={bookAuthor}
onChange={(event) => setBookAuthor(event.target.value)}
/>
</fieldset>
<fieldset>
<button type="submit">Add book</button>
</fieldset>
</form>
)
})
Thanks to the form, we can store books in our Redux store. Next thing we can do is create some list showing all books that are currently in the store. We can also add some button to remove specific book from the list, and the store. To do this, we will have to do a couple of things.
First, we will again have to use the useDispatch()
hook to get the dispatch()
method so we can update our store. Now, the reducer we will dispatch will be the removeBook
. We will import this reducer from src/store/books.js
. We will handle removing books with new handler function called onBookRemove()
.
This function will accept one parameter: bookId
. It will pass this id as a payload to the removeBook
reducer, and pass this reducer to the dispatch()
method. The payload will be an object with id
property and id of the book we want to remove. In order to list the books in store, we will need to get them somehow.
We can get those books by using the useSelector()
hook, also provided by react-redux
. This hook allows us to access the redux store’s state, the books state in our case. All we need is to provide this hook with a selector function to get the data we want.
The hook passes state
as an argument to the selector function. We will use this argument to get the booksReducer
we registered when we configured the Redux store (in src/store/index.js
). This reducer contains the slice we created for our books collection. The name of this slice is books
.
We defined this name in src/store/books.js
. It is the name
property in createSlice()
method. We will now use this name to access the books slice. The state of this slice is the array for our books collection. When we have this, we can use map()
to iterate over the books array to generate and display a list of all books in collection.
// src/BookList.jsx
// Import dependencies:
import { memo, useCallback } from 'react'
import { useDispatch, useSelector } from 'react-redux'
// Import removeBook reducer:
import { removeBook } from './store/books'
// Create BooksList component:
export const BooksList = memo(() => {
// Get books from Redux store:
const books = useSelector((state) => state.booksReducer.books)
// Prepare dispatch method:
const dispatch = useDispatch()
// Create handler for removing book:
const onBookRemove = useCallback(
(bookId) => {
dispatch(removeBook({ id: bookId }))
},
[dispatch]
)
return (
<div className="booklist">
{books.map((book) => (
<div key={book.bookTitle} className="book">
{`${book.bookTitle} by ${book.bookAuthor}`}
<button
className="removeButton"
onClick={() => onBookRemove(book.id)}
>
×
</button>
</div>
))}
</div>
)
})
Redux, form and book list components are ready. We can now put these components together in the App
component. Along with this, we can also add a heading showing how many books we have in our collection. We will get this number by using the useSelector
hook to get the books state.
In this case, instead of asking for state.booksReducer.books
we can ask directly for the number of books in the state. We can do this by adding the length
property: state.booksReducer.books.length
. This will return the number of books in the store instead of the array itself.
// src/App.jsx
// Import dependencies:
import { memo } from 'react'
import { useSelector } from 'react-redux'
// Import components:
import { BooksList } from './BooksList'
import { Form } from './Form'
// Create App component:
export const App = memo(() => {
// Get books from Redux store:
const booksCount = useSelector((state) => state.booksReducer.books.length)
return (
<div className="app">
<h1>Books in collection: {booksCount}</h1>
<Form />
{booksCount > 0 && <BooksList />}
</div>
)
})
The index.jsx
where we added the Redux Provider
component stayed the same. No change is necessary here.
// src/index.jsx
// Import React deps:
import { StrictMode } from 'react'
import ReactDOM from 'react-dom'
// Import Redux provider:
import { Provider } from 'react-redux'
// Import some styles:
import './styles.css'
// Import redux store:
import { store } from './store'
// Import main App component:
import { App } from './App'
// Render the React app:
const rootElement = document.getElementById('root')
ReactDOM.render(
<StrictMode>
{/* Add Redux provider */}
<Provider store={store}>
<App />
</Provider>
</StrictMode>,
rootElement
)
The whole flow of setting up even a simple Redux store used to be tedious and lengthy. Developers had to write a lot of code to just get started. This is no longer the case thanks to Redux toolkit. I hope that this tutorial helped you learn how to create a simple Redux store and how to implement it in your React app.
Demo on Codesandbox.
Original article sourced at: https://blog.alexdevero.com
1615623540
Redux Toolkit is an opinionated, batteries-included toolset for efficient Redux development. In this article, you will see why the Redux Toolkit deserves more attention in the React community.
React and Redux believed to be the best combo for managing state in large-scale React applications. However, with time, the popularity of Redux fallen due to;
With these issues, the creator of Redux Dan Abramov published the article called You Might Not Need Redux , which advises people to use Redux only when it needs and to follow other methods when developing less complex applications.
#redux-toolkit #redux #react
1595681400
Redux Toolkit popularity is growing every month. What exactly helps developers to write code faster, easier, more clearly? One of the helpers is createSlice
function. createSlice
takes an object of reducer functions, a slice name, and an initial state value and lets us auto-generate action types and action creators, based on the names of the reducer functions that we supply. It also helps you organize all of your Redux-related logic for a given slice into a single file.
It’s a function that deals with everything you need for each slice, do you remember using createAction
and createReducer
manually? Now it’s available in this specific slice function.
So what the returned object from createSlice
contains:
name
: a parameter that will be the prefix for all of your action typesinitialState
: the initial values for our reducerreducers
: it’s an object where the keys will become action type strings, and the functions are reducers that will be run when that action type is dispatched.The other benefit of using createSlice
is our files structure. We can put all of our Redux-related logic for the slice into a single file. You’ll see how to do it in our tutorial.
We have made basic Redux configuration with Redux Toolkit. But what is the most important benefit of using Toolkit? Definitely, it’s createSlice
function that you will probably use for most application you’re developing.
If you don’t want to start from zero, you can use our basic Redux configuration with Redux Toolkit.
To our previous little app with fake authorization, we’re gonna add a feature to show users data to logged user.
Firstly let’s create file src/store/users.js
and create our slice:
import { createSlice } from '@reduxjs/toolkit'
// Slice
const slice = createSlice({
name: 'users',
initialState: {
users: []
},
reducers: {
getUsers: (state, action) => {
state.users = action.payload;
},
},
});
export default slice.reducer
That’s basic slice configuration, it contains name
, initialState
and reducers
parameters.
Now let’s add actions. To keep it clear and simply add it in our slice’s file. We don’t have to write them individually in separate file anymore. We can export all the actions. the reducer, the asynchronous thunk and selector
that gives us access to state from any component without using connect
.
import { createSlice } from '@reduxjs/toolkit'
+ import { api } from '../api/index'
// Slice
const slice = createSlice({
name: 'users',
initialState: {
users: [],
},
reducers: {
usersSuccess: (state, action) => {
state.users = action.payload;
state.isLoading = false;
},
},
});
export default slice.reducer
// Actions
+ const { usersSuccess } = slice.actions
+ export const fetchUsers = () => async dispatch => {
+ try {
+ await api.get('/users')
+ .then((response) => dispatch(usersSuccess(response.data)))
+ }
+ catch (e) {
+ return console.error(e.message);
+ }
+}
#react #front-end-development #redux #software-development #startup #redux toolkit
1595688780
Do you have experience using React? Have you heard of Redux, but you’ve put off learning it because it looks very complicated and all the guides seem overwhelming? If that’s the case, this is the article for you! Contain your fear of containing state and come along with me on this relatively painless journey.
You must already know how to use React for this tutorial, as I will not be explaining any aspects of React itself.
Also, download Redux DevTools for Chrome or for FireFox.
In this tutorial, we will build a small blog app. It will fetch posts and comments from an API. I’ve created the same app with both plain Redux, and Redux Toolkit (RTK), the officially sanctioned toolset for Redux. Here are the links to the source and demos of both the plain and RTK versions.
Note: The applications are pulling from a real API via JSON Placeholder API. Due to rate limiting on CodeSandbox, the API may appear slow, but it has nothing to do with the Redux application itself. You can also clone the repository locally.
Redux is a state container for JavaScript applications. Normally with React, you manage state at a component level, and pass state around via props. With Redux, the entire state of your application is managed in one immutable object. Every update to the Redux state results in a copy of sections of the state, plus the new change.
Redux was originally created by Dan Abramov and Andrew Clark.
The downside to Redux is that there’s a lot of initial boilerplate to set up and maintain (especially if you use plain Redux without Redux Toolkit). A smaller application may not need Redux and may instead benefit from simply using the Context API for global state needs.
In my personal experience, I set up an application with Context alone, and later needed to convert everything over to Redux to make it more maintainable and organized.
Usually I don’t like to just make a list of terms and definitions, but Redux has a few that are likely unfamiliar, so I’m just going to define them all up front to make it easy to refer back to them. Although you can skip to the beginning of the tutorial section, I think it would be good to read through all the definitions just to get exposure and an idea of them in your head first.
I’ll just use the typical todo application, and the action of deleting a todo, for the examples.
#redux #react #tutorial #redux toolkit #programming