The new magical Redux land.
Tags: redux, react, magicthegathering
Published: 2021-08-19 08:17:48

---
title: The new magical Redux land.
published: true
description: Toss a function to your reducer. O'state of plenty!
tags: redux, react, magicthegathering
//cover_image: https://direct_url_to_image.jpg
---

This post assumes you have worked somewhat with Redux before, so apologies in advance if the syntax/explanations make little sense to you. 🖖

## In the beginning...

...back in the age of class components, a fair amount of tutorials out there would always teach React + Redux together, like they were necessarily part of each other.

What often happened is the steep learning curve of those two put together would make people have not so positive feelings towards one or the other (but very likely Redux was the one liked the least).

![Knowledge](https://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=489739&type=card)
<figcaption>Dispatch, reducers, action creators, containers...</figcaption>

I mean, looking back, I can understand the feeling very well. 

What I experienced: 

```javascript
// Having your container components (the ones that do the Redux magic)  

function mapStateToProps(state) {
  // Pass the global state down as you want it
}

function mapDispatchToProps(dispatch) {
  // Bind your action creators and have your components accessing them
}

export default connect(mapStateToProps, mapDispatchToProps)(MyContainerComponent);
```

Then wrap all the components under your container component and go to Redux town. Now you are able to update and read the global state in your application. 

Oh and don't forget your reducers!

I remember when our team back then was going through all that and often feeling overwhelmed, because of so many layers, so many moving parts. Little did I know what the future would hold.

But I ended up not using redux for nearly two years because of my new job. We didn't need it, so I never heard of it again, until...

![Tomorrow](https://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=522205&type=card)
<figcaption>Fast forward 2 years.</figcaption>

## Another day, another side project

Recently, during a random talk with a good colleague of mine, he mentioned being enthusiastic about Redux and that sparked my curiosity, so I decided to check it out, and oh boy.

![New perspectives](https://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=426765&type=card)

We can build something cool with it.

## Let's fetch Magic The Gathering cards. 

In order to get started, we need a store. 

```javascript
// src/store/index.js

import { configureStore } from "@reduxjs/toolkit";

const store = configureStore({ reducer: {} });

export default store;
```

That's it. [In their docs](https://redux-toolkit.js.org/usage/usage-guide) you can check how it was before, and the pleasants surprises didn't stop there.

Now we need reducers.

Redux Toolkit has `reducer slices`, and `what are those`? 

> slice reducer: a reducer that is being used to handle updates to one specific slice of the state tree, usually done by passing it to combineReducers

([from their docs](https://redux.js.org/usage/structuring-reducers/splitting-reducer-logic))

Basically, it's a more focused reducer, it's easier to split the state changing logic instead of having one gigantic reducer that does a lot.

This is how you create a slice:

```javascript
// src/features/search/searchSlice.js

import { createSlice } from "@reduxjs/toolkit";

const initialState = {
  searchString: ""
};

export const searchSlice = createSlice({
  name: "search",
  initialState,
  reducers: {
    searchCard: (state, action) => {
      // Redux Toolkit allows us to write "mutating" logic in reducers. It
      // doesn't actually mutate the state because it uses the Immer library,
      // which detects changes to a "draft state" and produces a brand new
      // immutable state based off those changes
      state.searchString = action.payload;
    }
  }
});

// Action creators are generated for each case reducer function
export const { searchCard } = searchSlice.actions;

export default searchSlice.reducer;

```

Like it's mentioned in the code and their docs, there's no need for spreading objects over and over again. Redux Toolkit already takes care of the immutability for you, so feel free to assign the value to the state directly. Never again overwriting the state by accident!

Notice how we didn't have to create any actions? `createSlice` already does it for you, combined with a reducer. But if you want to create those by hand, feel free to check the `createReducer` on their API. 

Cool, our slice is ready. We can finally connect it to the store:

```javascript
// src/store/index.js

import { configureStore } from "@reduxjs/toolkit";
import searchReducer from "../features/search/searchSlice";

export const store = configureStore({
  reducer: {
    search: searchReducer
  }
});

```

Now we're ready to use it in our components.

## Interacting with our components

![Past](https://gatherer.wizards.com/Handlers/Image.ashx?multiverseid=513544&type=card)

Remember `connect`, `mapStateToProps` and `mapDispatchToProps`?

This is them now, feel old? 

```javascript
const search = useSelector((state) => state.search);
const dispatch = useDispatch();
```

`useSelector` is how we tap into the global state shared by your store. 

And `useDispatch` allows us to dispatch our actions. But where do we get our actions from? 

From the slice! 🤩

```javascript
import { search } from "./features/search/searchSlice";
```

Putting it all together: 

```javascript
// src/App.js
import { useDispatch, useSelector } from "react-redux";

import { searchCard } from "./features/search/searchSlice";
import "./styles.css";
import { useCallback, useEffect, useState } from "react";
import { useUpdateEffect } from "react-use";

export default function App() {
  const searchState = useSelector((state) => state.search);
  const [card, setCard] = useState(null);

  const dispatch = useDispatch();

  const handleChange = useCallback(
    (searchString) => {
      if (!searchString) return;

      fetch(
        `https://api.scryfall.com/cards/named?fuzzy=${encodeURI(searchString)}`
      )
        .then((response) => response.json())
        .then((jsonResponse) => setCard(jsonResponse));
    },
    [setCard]
  );

  useUpdateEffect(() => {
    handleChange(searchState.searchString);
  }, [searchState]);

  return (
    <div className="App">
      <h1>
        Would you like a magic card?{" "}
        <span role="img" aria-label="card">
          🃏
        </span>
      </h1>
      <div style={{ marginBottom: "2rem" }}>
        <label htmlFor="card-search">Card select: </label>
        <select
          id="card-seard"
          onChange={(event) => dispatch(searchCard(event.target.value))}
        >
          <option value="">Choose one</option>
          <option value="lightning bolt">Lightning bolt</option>
          <option value="ancestral recall">Ancestral Recall</option>
        </select>
      </div>
      <div>
        {card?.image_uris && (
          <img
            src={card.image_uris.normal}
            alt={card.name}
            style={{ height: "300px" }}
          />
        )}
      </div>
    </div>
  );
}



```

I'll leave the running sandbox here:

{% codesandbox romantic-best-potato-kpk92 %}

## Conclusion

Despite this being a simple example to add Redux on, I wanted to share how much easier it is to get started on it. Something I plan to write about later is their [RTK (Redux Toolkit) Query](https://redux-toolkit.js.org/rtk-query/overview). Adding on this post would make it too convoluted. 

I was completely blown away from what it can do and I definitely recommend checking it out. 

After playing around with all for a bit, I ended up creating this fun side project, take a look if you're into tabletop RPGs: www.yougotaquest.com