How to Build A Simple Redux Store with Redux Toolkit

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.

About the project and dependencies

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.

Creating Redux store

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.

Redux state slice

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

Configuring Redux store

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
  },
})

Adding Redux provider

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 Form component

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>
  )
})

The BookList component

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)}
          >
            &times;
          </button>
        </div>
      ))}
    </div>
  )
})

The App component

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 file

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
)

Conclusion: How to create simple Redux store with Redux toolkit

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

#redux 

What is GEEK

Buddha Community

How to Build A Simple Redux Store with Redux Toolkit

How to Build A Simple Redux Store with Redux Toolkit

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.

About the project and dependencies

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.

Creating Redux store

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.

Redux state slice

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

Configuring Redux store

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
  },
})

Adding Redux provider

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 Form component

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>
  )
})

The BookList component

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)}
          >
            &times;
          </button>
        </div>
      ))}
    </div>
  )
})

The App component

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 file

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
)

Conclusion: How to create simple Redux store with Redux toolkit

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

#redux 

Noemi  Hintz

Noemi Hintz

1671544260

How to Build a Simple Redux Store with Redux Toolkit

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.

About the project and dependencies

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.

Creating Redux store

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.

Redux state slice

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

Configuring Redux store

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
  },
})

Adding Redux provider

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 Form component

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>
  )
})

The BookList component

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)}
          >
            &times;
          </button>
        </div>
      ))}
    </div>
  )
})

The App component

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 file

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
)

Conclusion: How to create simple Redux store with Redux toolkit

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

#redux 

Simplifying Redux with Redux Toolkit

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;

  • Configuring a Redux store is not simple.
  • We need several packages to get Redux to work with React.
  • Redux requires too much boilerplate code.

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

Sidney  Purdy

Sidney Purdy

1595681400

How To Setup Redux Slices with Redux Toolkit

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.

What is createSlice?

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 types
  • initialState: the initial values for our reducer
  • reducers: 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.

Slice configuration

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 nameinitialState and reducers parameters.

Adding actions

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

Sidney  Purdy

Sidney Purdy

1595688780

Redux Tutorial: An Overview and Walkthrough with React + Redux Toolkit

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.

Prerequisites

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.

Goals

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.

React + Redux Application (Plain Redux)

React + Redux Toolkit Application

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.

We will learn:

  • What is Redux and why you might want to use it
  • The terminology of Redux: actions, reducers, store, dispatch, connect, and container
  • Making asynchronous API calls with Redux Thunk
  • How to make a small, real-world application with React and Redux
  • How to use Redux Toolkit to simplify Redux app development

What is Redux?

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.

Why should I use Redux?

  • Easily manage global state - access or update any part of the state from any Redux-connected component
  • Easily keep track of changes with Redux DevTools - any action or state change is tracked and easy to follow with Redux. The fact that the entire state of the application is tracked with each change means you can easily do time-travel debugging to move back and forth between changes.

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.

Terminology

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