Connecting Redux to the Application

In notebook:
FrontEndMasters Intermediate React
Created at:
2019-06-25
Updated:
2019-08-15
Tags:
React libraries JavaScript

https://frontendmasters.com/courses/intermediate-react-v2/connecting-redux-to-the-application/

Uptade App.js

  --- a/src/App.js
+++ b/src/App.js
@@ -1,14 +1,14 @@
// don't need useState since it's a Redux "replacement"
-import React, { useState } from "react";
+import React from "react";
 import ReactDOM from "react-dom";
 import { Router, Link } from "@reach/router";
+ // this will provide the Redux store to the entire application
+import { Provider } from "react-redux";
+ // need the store as well
+import store from "./store";
 import Details from "./Details";
 import SearchParams from "./SearchParams";
-import ThemeContext from "./ThemeContext";
 
 const App = () => {
-  const theme = useState("darkblue");
   return (
-    <ThemeContext.Provider value={theme}>
// add the provider
// and now Redux is available to the entire App
+    <Provider store={store}>
       <div>
         <header>
           <Link to="/">Adopt Me!</Link>
@@ -19,7 +19,7 @@ const App = () => {
           <Details path="/details/:id" />
         </Router>
       </div>
-    </ThemeContext.Provider>
+    </Provider>
   );
 };
 

update SearchParams

  import React, { useState, useEffect, useContext } from "react";
import pet, { ANIMALS } from "@frontendmasters/pet";
// **** 1. import connect.  ↴
import { connect } from "react-redux";
import useDropdown from "./useDropdown";
import Results from "./Results";
import changeLocation from "./actionCreator/changeLocation";
import changeTheme from "./actionCreator/changeTheme";

// **** 4. provide the props here.  ↴
const SearchParams = props => ({ theme, location, setTheme, updateLocation }) => {
 // **** 2. can delete the context refences.  ↴
 //- const [theme  setTheme] = useContext(ThemeContext)
  const [breeds, updateBreeds] = useState([]);
  const [pets, setPets] = useState([]);
  const [animal, AnimalDropdown] = useDropdown("Animal", "dog", ANIMALS);
  const [breed, BreedDropdown, updateBreed] = useDropdown("Breed", "", breeds);

  async function requestPets() {
    const { animals } = await pet.animals({
     // **** 3. update location.  ↴
      location: props.location,
      breed,
      type: animal
    });

    setPets(animals || []);
  }

  useEffect(() => {
    updateBreeds([]);
    updateBreed("");

    pet.breeds(animal).then(({ breeds }) => {
      const breedStrings = breeds.map(({ name }) => name);
      updateBreeds(breedStrings);
    }, console.error);
  }, [animal]);

  return (
    <div className="search-params">
      <form
        onSubmit={e => {
          e.preventDefault();
          requestPets();
        }}
      >
        <label htmlFor="location">
          Location
          <input
            id="location"
            // **** 5. update props.location here.  ↴
            value={props.location}
            placeholder="Location"
            // **** 6. use again props here.  ↴
            onChange={e => props.updateLocation(e.target.value)}
          />
        </label>
        <AnimalDropdown />
        <BreedDropdown />
        <label htmlFor="location">
          Theme
          <select
           // **** 7 again change to props.theme.  ↴
            value={props.theme}
             // **** 8 and setTheme to props.setTheme.  ↴
            onChange={e => props.setTheme(e.target.value)}
            onBlur={e => props.setTheme(e.target.value)}
          >
            <option value="peru">Peru</option>
            <option value="darkblue">Dark Blue</option>
            <option value="chartreuse">Chartreuse</option>
            <option value="mediumorchid">Medium Orchid</option>
          </select>
        </label>
        <button style={{ backgroundColor: props.theme }}>Submit</button>
      </form>
      <Results pets={pets} />
    </div>
  );
};

// **** 9. start integrating Redux here.  ↴
// this will extract state from Redux
// and pass to the component
const mapStateToProps = ({ theme, location }) => ({
  theme,
  location
});

// **** 10. add the dispatch.  ↴
// so that we can send updates to Redux
const mapDispatchToProps = dispatch => ({
  // in the workshop it's called updateLocation...
  setLocation(location) {
    // changeLocation is from the actionCreators ↴
    dispatch(changeLocation(location));
  },
  setTheme(theme) {
    dispatch(changeTheme(theme));
  }
});

// **** 11. use the connect. ↴
// it's a bit strange pattern, to call a function
// that returns a function
// its because you will be able to use
// connect as a decorator later
export default connect(
  mapStateToProps,
  mapDispatchToProps
)(SearchParams);

Now, the Location state is no longer held by the the SearchParams component, but lives in redux.