Skip to content
This repository has been archived by the owner on Jun 12, 2022. It is now read-only.

Commit

Permalink
feat: use createAsyncThunk for handling the api call
Browse files Browse the repository at this point in the history
  • Loading branch information
rrebase committed Mar 26, 2020
1 parent 7e3da06 commit 1d2d5a8
Show file tree
Hide file tree
Showing 4 changed files with 45 additions and 64 deletions.
29 changes: 11 additions & 18 deletions template/src/features/counter/Counter.test.tsx
Original file line number Diff line number Diff line change
@@ -1,15 +1,10 @@
import { screen, fireEvent, wait } from "@testing-library/react";
import Counter from "./Counter";
import React from "react";
import counterReducer, {
increment,
decrement,
fetchValueStart,
fetchValueSuccess,
fetchValueError
} from "./CounterSlice";
import counterReducer, { increment, decrement } from "./CounterSlice";
import { renderWithRedux, rootInitialState } from "utils/test-helpers";
import axios from "axios";
import { fetchInitial } from "./CounterSlice";

jest.mock("axios");
const mockedAxios = axios as jest.Mocked<typeof axios>;
Expand Down Expand Up @@ -63,10 +58,9 @@ describe("<Counter />", () => {
// https://github.com/testing-library/react-testing-library#complex-example
await wait(() => null, { timeout: 500 });

expect(mockStore.getActions()).toEqual([
{ type: fetchValueStart.type, payload: undefined },
{ type: fetchValueSuccess.type, payload: name.length }
]);
expect(mockStore.getActions()[0].type).toEqual(fetchInitial.pending.type);
expect(mockStore.getActions()[1].type).toEqual(fetchInitial.fulfilled.type);
expect(mockStore.getActions()[1].payload).toEqual(name.length);
});

test("slow fetch error", async () => {
Expand All @@ -82,10 +76,9 @@ describe("<Counter />", () => {
// https://github.com/testing-library/react-testing-library#complex-example
await wait(() => null, { timeout: 500 });

expect(mockStore.getActions()).toEqual([
{ type: fetchValueStart.type, payload: undefined },
{ type: fetchValueError.type, payload: "Something went wrong." }
]);
expect(mockStore.getActions()[0].type).toEqual(fetchInitial.pending.type);
expect(mockStore.getActions()[1].type).toEqual(fetchInitial.rejected.type);
expect(mockStore.getActions()[1].payload).toEqual("Something went wrong.");
});
});

Expand All @@ -94,7 +87,7 @@ describe("CounterSlice", () => {
expect(
counterReducer(
{ ...rootInitialState.counter, loading: false },
fetchValueStart
fetchInitial.pending
)
).toEqual({ ...rootInitialState.counter, loading: true });
});
Expand All @@ -103,7 +96,7 @@ describe("CounterSlice", () => {
expect(
counterReducer(
{ ...rootInitialState.counter, loading: true },
{ type: fetchValueSuccess, payload: 100 }
{ type: fetchInitial.fulfilled.type, payload: 100 }
)
).toEqual({ ...rootInitialState.counter, loading: false, value: 100 });
});
Expand All @@ -112,7 +105,7 @@ describe("CounterSlice", () => {
expect(
counterReducer(
{ ...rootInitialState.counter, loading: true },
{ type: fetchValueError, payload: "Some error message." }
{ type: fetchInitial.rejected, payload: "Some error message." }
)
).toEqual({
...rootInitialState.counter,
Expand Down
5 changes: 2 additions & 3 deletions template/src/features/counter/Counter.tsx
Original file line number Diff line number Diff line change
@@ -1,8 +1,7 @@
import React from "react";
import { useDispatch, useSelector } from "react-redux";
import styles from "./Counter.module.scss";
import { increment, decrement } from "./CounterSlice";
import { fetchInitialValue } from "./CounterActions";
import { increment, decrement, fetchInitial } from "./CounterSlice";
import { RootState } from "store";

const Counter: React.FC = () => {
Expand Down Expand Up @@ -46,7 +45,7 @@ const Counter: React.FC = () => {
<button
className={styles.button}
aria-label="Slow fetch"
onClick={() => dispatch(fetchInitialValue())}
onClick={() => dispatch(fetchInitial())}
disabled={loading}
>
Slow fetch
Expand Down
26 changes: 0 additions & 26 deletions template/src/features/counter/CounterActions.tsx

This file was deleted.

49 changes: 32 additions & 17 deletions template/src/features/counter/CounterSlice.tsx
Original file line number Diff line number Diff line change
@@ -1,4 +1,8 @@
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
import { createSlice, createAsyncThunk } from "@reduxjs/toolkit";
import axios from "axios";

const sleep = (t = Math.random() * 200 + 300) =>
new Promise(resolve => setTimeout(resolve, t));

interface InitialState {
value: number;
Expand All @@ -12,36 +16,47 @@ export const initialState: InitialState = {
error: null
};

export const fetchInitial = createAsyncThunk(
"counter/fetchInitial",
async (_, { rejectWithValue }) => {
try {
// For demo purpose let's say out value is the length
// of the project name in manifest and the api call is slow
await sleep();
const response = await axios.get("/manifest.json");
return response.data.name.length;
} catch (err) {
return rejectWithValue("Something went wrong.");
}
}
);

export const slice = createSlice({
name: "counter",
initialState,
reducers: {
fetchValueStart: state => {
increment: state => {
state.value += 1;
},
decrement: state => {
state.value -= 1;
}
},
extraReducers: {
[fetchInitial.pending.type]: state => {
state.loading = true;
},
fetchValueSuccess: (state, action: PayloadAction<number>) => {
[fetchInitial.fulfilled.type]: (state, action) => {
state.value = action.payload;
state.loading = false;
},
fetchValueError: (state, action: PayloadAction<string>) => {
[fetchInitial.rejected.type]: (state, action) => {
state.error = action.payload;
state.loading = false;
},
increment: state => {
state.value += 1;
},
decrement: state => {
state.value -= 1;
}
}
});

export const {
fetchValueStart,
fetchValueSuccess,
fetchValueError,
increment,
decrement
} = slice.actions;
export const { increment, decrement } = slice.actions;

export default slice.reducer;

0 comments on commit 1d2d5a8

Please sign in to comment.