├── tsconfig.json ├── .gitignore ├── public └── index.html ├── package.json ├── README.md └── src ├── index.tsx └── es2021.intl.d.ts /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "target": "es2021", 4 | "module": "commonjs", 5 | "esModuleInterop": true, 6 | "forceConsistentCasingInFileNames": true, 7 | "strict": true, 8 | "skipLibCheck": true, 9 | "jsx": "react" 10 | } 11 | } 12 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # See https://help.github.com/articles/ignoring-files/ for more about ignoring files. 2 | 3 | # dependencies 4 | /node_modules 5 | /.pnp 6 | .pnp.js 7 | 8 | # testing 9 | /coverage 10 | 11 | # production 12 | /build 13 | 14 | # misc 15 | .DS_Store 16 | .env.local 17 | .env.development.local 18 | .env.test.local 19 | .env.production.local 20 | 21 | npm-debug.log* 22 | yarn-debug.log* 23 | yarn-error.log* 24 | -------------------------------------------------------------------------------- /public/index.html: -------------------------------------------------------------------------------- 1 | 2 | 3 | 4 | 5 | 6 | 7 | My Pokedex 8 | 9 | 10 | 11 |
12 | 13 | 14 | -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "lesson-one", 3 | "version": "0.1.0", 4 | "private": true, 5 | "dependencies": { 6 | "@reduxjs/toolkit": "^1.8.1", 7 | "@testing-library/jest-dom": "^5.16.4", 8 | "@testing-library/react": "^13.0.1", 9 | "@testing-library/user-event": "^13.5.0", 10 | "react": "^18.0.0", 11 | "react-dom": "^18.0.0", 12 | "react-redux": "^7.2.8", 13 | "react-scripts": "5.0.1", 14 | "typescript": "^4.6.3", 15 | "web-vitals": "^2.1.4" 16 | }, 17 | "scripts": { 18 | "start": "react-scripts start", 19 | "build": "react-scripts build", 20 | "test": "react-scripts test", 21 | "eject": "react-scripts eject" 22 | }, 23 | "eslintConfig": { 24 | "extends": [ 25 | "react-app", 26 | "react-app/jest" 27 | ] 28 | }, 29 | "browserslist": { 30 | "production": [ 31 | ">0.2%", 32 | "not dead", 33 | "not op_mini all" 34 | ], 35 | "development": [ 36 | "last 1 chrome version", 37 | "last 1 firefox version", 38 | "last 1 safari version" 39 | ] 40 | } 41 | } 42 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Code for the EggHead course [RTK Query Basics: Query Endpoints, Data Flow and TypeScript](https://egghead.io/courses/rtk-query-basics-query-endpoints-data-flow-and-typescript-57ea3c43?af=7pnhj6) 2 | 3 | 1. Course Introduction and Application Walk through for RTK Query Basics [Code](https://github.com/phryneas/egghead-rtk-query-basics/tree/start) [Video](https://egghead.io/lessons/redux-course-introduction-and-application-walk-through-for-rtk-query-basics?af=7pnhj6) 4 | 2. Set up RTK Query with createAPI and ApiProvider that Serve Fake Data [Code](https://github.com/phryneas/egghead-rtk-query-basics/tree/createApi) [Video](https://egghead.io/lessons/redux-set-up-rtk-query-with-createapi-and-apiprovider-that-serve-fake-data?af=7pnhj6) 5 | 3. Fetch Data from a Live Endpoint with RTK Query [Code](https://github.com/phryneas/egghead-rtk-query-basics/tree/fetch) [Video](https://egghead.io/lessons/redux-fetch-data-from-a-live-endpoint-with-rtk-query?af=7pnhj6) 6 | 4. Pass Query Arguments to RTK Query Hooks [Code](https://github.com/phryneas/egghead-rtk-query-basics/tree/queryArgs) [Video](https://egghead.io/lessons/redux-pass-query-arguments-to-rtk-query-hooks?af=7pnhj6) 7 | 5. Refactor RTK Query Endpoints to use baseQuery to Remove Code Duplication [Code](https://github.com/phryneas/egghead-rtk-query-basics/tree/baseQuery) [Video](https://egghead.io/lessons/redux-refactor-rtk-query-endpoints-to-use-basequery-to-remove-code-duplication?af=7pnhj6) 8 | 6. Refactor baseQuery to use RTK Query fetchBaseQuery [Code](https://github.com/phryneas/egghead-rtk-query-basics/tree/fetchBaseQuery) [Video](https://egghead.io/lessons/redux-refactor-basequery-to-use-rtk-query-fetchbasequery?af=7pnhj6) 9 | 7. Convert a RTK Query Application to TypeScript [Code](https://github.com/phryneas/egghead-rtk-query-basics/tree/typescript) [Video](https://egghead.io/lessons/redux-convert-a-rtk-query-application-to-typescript?af=7pnhj6) 10 | 8. Explore Redux Devtools to Understand Your RTK Query App Data Fetching Behavior [Video](https://egghead.io/lessons/redux-explore-redux-devtools-to-understand-your-rtk-query-app-data-fetching-behavior?af=7pnhj6) 11 | 9. Refactor RTK Query to Use a Normal Redux Toolkit Store [Code](https://github.com/phryneas/egghead-rtk-query-basics/tree/configureStore) [Video](https://egghead.io/lessons/redux-refactor-rtk-query-to-use-a-normal-redux-toolkit-store?af=7pnhj6) 12 | -------------------------------------------------------------------------------- /src/index.tsx: -------------------------------------------------------------------------------- 1 | import React from "react"; 2 | import ReactDOM from "react-dom/client"; 3 | import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react"; 4 | 5 | import { configureStore } from "@reduxjs/toolkit"; 6 | import { Provider } from "react-redux"; 7 | 8 | interface PokemonListing { 9 | count: number; 10 | results: Array<{ 11 | name: string; 12 | url: string; 13 | }>; 14 | } 15 | 16 | interface PokemonDetailData { 17 | id: number; 18 | name: string; 19 | height: number; 20 | weight: number; 21 | types: Array<{ 22 | slot: number; 23 | type: { 24 | name: string; 25 | url: string; 26 | }; 27 | }>; 28 | sprites: { 29 | front_default: string; 30 | }; 31 | } 32 | 33 | const api = createApi({ 34 | baseQuery: fetchBaseQuery({ 35 | baseUrl: "https://pokeapi.co/api/v2/", 36 | }), 37 | endpoints: (build) => ({ 38 | pokemonList: build.query({ 39 | query() { 40 | return { 41 | // these are specific to `fetchBaseQuery` 42 | url: "pokemon", 43 | params: { limit: 9 }, 44 | // all the different arguments that you could also pass into the `fetch` "init" option 45 | // see https://developer.mozilla.org/en-US/docs/Web/API/fetch#parameters 46 | method: "GET", // GET is the default, this could be skipped 47 | }; 48 | }, 49 | }), 50 | pokemonDetail: build.query({ 51 | query: ({ name }) => `pokemon/${name}/`, 52 | }), 53 | }), 54 | }); 55 | 56 | const { usePokemonListQuery, usePokemonDetailQuery } = api; 57 | 58 | const store = configureStore({ 59 | reducer: { 60 | [api.reducerPath]: api.reducer, 61 | }, 62 | middleware: (getDefaultMiddleware) => 63 | getDefaultMiddleware().concat(api.middleware), 64 | }); 65 | 66 | const root = ReactDOM.createRoot(document.getElementById("root")!); 67 | root.render( 68 | 69 | 70 | 71 | 72 | 73 | ); 74 | 75 | function App() { 76 | const [selectedPokemon, selectPokemon] = React.useState( 77 | undefined 78 | ); 79 | 80 | return ( 81 | <> 82 |
83 |

My Pokedex

84 |
85 |
86 | {selectedPokemon ? ( 87 | <> 88 | 89 | 90 | 91 | ) : ( 92 | 93 | )} 94 |
95 | 96 | ); 97 | } 98 | 99 | function PokemonList({ 100 | onPokemonSelected, 101 | }: { 102 | onPokemonSelected: (pokemonName: string) => void; 103 | }) { 104 | const { isUninitialized, isLoading, isError, isSuccess, data } = 105 | usePokemonListQuery(); 106 | 107 | if (isLoading || isUninitialized) { 108 | return

loading, please wait

; 109 | } 110 | 111 | if (isError) { 112 | return

something went wrong

; 113 | } 114 | 115 | return ( 116 |
117 |

Overview

118 |
    119 | {data.results.map((pokemon) => ( 120 |
  1. 121 | 124 |
  2. 125 | ))} 126 |
127 |
128 | ); 129 | } 130 | 131 | const listFormatter = new Intl.ListFormat("en-GB", { 132 | style: "short", 133 | type: "conjunction", 134 | }); 135 | function PokemonDetails({ pokemonName }: { pokemonName: string }) { 136 | const { isUninitialized, isLoading, isError, isSuccess, data } = 137 | usePokemonDetailQuery({ 138 | name: pokemonName, 139 | }); 140 | 141 | if (isLoading || isUninitialized) { 142 | return

loading, please wait

; 143 | } 144 | 145 | if (isError) { 146 | return

something went wrong

; 147 | } 148 | 149 | return ( 150 |
151 |

{data.name}

152 | {data.name} 153 |
    154 |
  • id: {data.id}
  • 155 |
  • height: {data.height}
  • 156 |
  • weight: {data.weight}
  • 157 |
  • 158 | types: 159 | {listFormatter.format(data.types.map((item) => item.type.name))} 160 |
  • 161 |
162 |
163 | ); 164 | } 165 | -------------------------------------------------------------------------------- /src/es2021.intl.d.ts: -------------------------------------------------------------------------------- 1 | declare namespace Intl { 2 | interface DateTimeFormatOptions { 3 | formatMatcher?: "basic" | "best fit" | "best fit" | undefined; 4 | dateStyle?: "full" | "long" | "medium" | "short" | undefined; 5 | timeStyle?: "full" | "long" | "medium" | "short" | undefined; 6 | dayPeriod?: "narrow" | "short" | "long" | undefined; 7 | fractionalSecondDigits?: 0 | 1 | 2 | 3 | undefined; 8 | } 9 | 10 | interface DateTimeFormat { 11 | formatRange( 12 | startDate: Date | number | bigint, 13 | endDate: Date | number | bigint 14 | ): string; 15 | formatRangeToParts( 16 | startDate: Date | number | bigint, 17 | endDate: Date | number | bigint 18 | ): DateTimeFormatPart[]; 19 | } 20 | 21 | interface ResolvedDateTimeFormatOptions { 22 | formatMatcher?: "basic" | "best fit" | "best fit"; 23 | dateStyle?: "full" | "long" | "medium" | "short"; 24 | timeStyle?: "full" | "long" | "medium" | "short"; 25 | hourCycle?: "h11" | "h12" | "h23" | "h24"; 26 | dayPeriod?: "narrow" | "short" | "long"; 27 | fractionalSecondDigits?: 0 | 1 | 2 | 3; 28 | } 29 | 30 | /** 31 | * The locale matching algorithm to use. 32 | * 33 | * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters). 34 | */ 35 | type ListFormatLocaleMatcher = "lookup" | "best fit"; 36 | 37 | /** 38 | * The format of output message. 39 | * 40 | * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters). 41 | */ 42 | type ListFormatType = "conjunction" | "disjunction" | "unit"; 43 | 44 | /** 45 | * The length of the formatted message. 46 | * 47 | * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters). 48 | */ 49 | type ListFormatStyle = "long" | "short" | "narrow"; 50 | 51 | /** 52 | * An object with some or all properties of the `Intl.ListFormat` constructor `options` parameter. 53 | * 54 | * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters). 55 | */ 56 | interface ListFormatOptions { 57 | /** The locale matching algorithm to use. For information about this option, see [Intl page](https://developer.mozilla.org/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_negotiation). */ 58 | localeMatcher?: ListFormatLocaleMatcher | undefined; 59 | /** The format of output message. */ 60 | type?: ListFormatType | undefined; 61 | /** The length of the internationalized message. */ 62 | style?: ListFormatStyle | undefined; 63 | } 64 | 65 | interface ListFormat { 66 | /** 67 | * Returns a string with a language-specific representation of the list. 68 | * 69 | * @param list - An iterable object, such as an [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array). 70 | * 71 | * @throws `TypeError` if `list` includes something other than the possible values. 72 | * 73 | * @returns {string} A language-specific formatted string representing the elements of the list. 74 | * 75 | * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/format). 76 | */ 77 | format(list: Iterable): string; 78 | 79 | /** 80 | * Returns an Array of objects representing the different components that can be used to format a list of values in a locale-aware fashion. 81 | * 82 | * @param list - An iterable object, such as an [Array](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Array), to be formatted according to a locale. 83 | * 84 | * @throws `TypeError` if `list` includes something other than the possible values. 85 | * 86 | * @returns {{ type: "element" | "literal", value: string; }[]} An Array of components which contains the formatted parts from the list. 87 | * 88 | * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/formatToParts). 89 | */ 90 | formatToParts( 91 | list: Iterable 92 | ): { type: "element" | "literal"; value: string }[]; 93 | } 94 | 95 | const ListFormat: { 96 | prototype: ListFormat; 97 | 98 | /** 99 | * Creates [Intl.ListFormat](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat) objects that 100 | * enable language-sensitive list formatting. 101 | * 102 | * @param locales - A string with a [BCP 47 language tag](http://tools.ietf.org/html/rfc5646), or an array of such strings. 103 | * For the general form and interpretation of the `locales` argument, 104 | * see the [`Intl` page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation). 105 | * 106 | * @param options - An [object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/ListFormat#parameters) 107 | * with some or all options of `ListFormatOptions`. 108 | * 109 | * @returns [Intl.ListFormatOptions](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat) object. 110 | * 111 | * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat). 112 | */ 113 | new ( 114 | locales?: BCP47LanguageTag | BCP47LanguageTag[], 115 | options?: ListFormatOptions 116 | ): ListFormat; 117 | 118 | /** 119 | * Returns an array containing those of the provided locales that are 120 | * supported in list formatting without having to fall back to the runtime's default locale. 121 | * 122 | * @param locales - A string with a [BCP 47 language tag](http://tools.ietf.org/html/rfc5646), or an array of such strings. 123 | * For the general form and interpretation of the `locales` argument, 124 | * see the [`Intl` page](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl#Locale_identification_and_negotiation). 125 | * 126 | * @param options - An [object](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/supportedLocalesOf#parameters). 127 | * with some or all possible options. 128 | * 129 | * @returns An array of strings representing a subset of the given locale tags that are supported in list 130 | * formatting without having to fall back to the runtime's default locale. 131 | * 132 | * [MDN](https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Intl/ListFormat/supportedLocalesOf). 133 | */ 134 | supportedLocalesOf( 135 | locales: BCP47LanguageTag | BCP47LanguageTag[], 136 | options?: Pick 137 | ): BCP47LanguageTag[]; 138 | }; 139 | } 140 | --------------------------------------------------------------------------------