├── 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 |
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 | -
121 |
124 |
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 |
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 |
--------------------------------------------------------------------------------