aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
Diffstat (limited to '')
-rw-r--r--src/App.jsx51
-rw-r--r--src/App.test.jsx15
-rw-r--r--src/app/store.js6
-rw-r--r--src/features/counter/Counter.jsx63
-rw-r--r--src/features/counter/Counter.module.css78
-rw-r--r--src/features/counter/counterAPI.js6
-rw-r--r--src/features/counter/counterSlice.js68
-rw-r--r--src/features/counter/counterSlice.spec.js33
-rw-r--r--src/logo.svg1
-rw-r--r--src/main.jsx2
10 files changed, 29 insertions, 294 deletions
diff --git a/src/App.jsx b/src/App.jsx
index e28ac6e..7fbcae5 100644
--- a/src/App.jsx
+++ b/src/App.jsx
@@ -1,56 +1,11 @@
import React from "react";
-import logo from "./logo.svg";
-import { Counter } from "./features/counter/Counter";
import "./App.css";
+import { Counter } from "./features/counter/Counter";
function App() {
return (
- <div className="App">
- <header className="App-header">
- <img src={logo} className="App-logo" alt="logo" />
- <Counter />
- <p>
- Edit <code>src/App.js</code> and save to reload.
- </p>
- <span>
- <span>Learn </span>
- <a
- className="App-link"
- href="https://reactjs.org/"
- target="_blank"
- rel="noopener noreferrer"
- >
- React
- </a>
- <span>, </span>
- <a
- className="App-link"
- href="https://redux.js.org/"
- target="_blank"
- rel="noopener noreferrer"
- >
- Redux
- </a>
- <span>, </span>
- <a
- className="App-link"
- href="https://redux-toolkit.js.org/"
- target="_blank"
- rel="noopener noreferrer"
- >
- Redux Toolkit
- </a>
- ,<span> and </span>
- <a
- className="App-link"
- href="https://react-redux.js.org/"
- target="_blank"
- rel="noopener noreferrer"
- >
- React Redux
- </a>
- </span>
- </header>
+ <div>
+ <Counter />
</div>
);
}
diff --git a/src/App.test.jsx b/src/App.test.jsx
deleted file mode 100644
index e4874f8..0000000
--- a/src/App.test.jsx
+++ /dev/null
@@ -1,15 +0,0 @@
-import React from "react";
-import { render } from "@testing-library/react";
-import { Provider } from "react-redux";
-import { store } from "./app/store";
-import App from "./App";
-
-test("renders learn react link", () => {
- const { getByText } = render(
- <Provider store={store}>
- <App />
- </Provider>
- );
-
- expect(getByText(/learn/i)).toBeInTheDocument();
-});
diff --git a/src/app/store.js b/src/app/store.js
index f5b8ae3..012eb09 100644
--- a/src/app/store.js
+++ b/src/app/store.js
@@ -1,8 +1,8 @@
-import { configureStore } from "@reduxjs/toolkit";
-import counterReducer from "../features/counter/counterSlice";
+import { configureStore } from '@reduxjs/toolkit'
+import counterReducer from '../features/counter/counterSlice'
export const store = configureStore({
reducer: {
counter: counterReducer,
},
-});
+})
diff --git a/src/features/counter/Counter.jsx b/src/features/counter/Counter.jsx
index 37d866d..d589bf9 100644
--- a/src/features/counter/Counter.jsx
+++ b/src/features/counter/Counter.jsx
@@ -1,67 +1,28 @@
-import React, { useState } from "react";
-import { useSelector, useDispatch } from "react-redux";
-import {
- decrement,
- increment,
- incrementByAmount,
- incrementAsync,
- incrementIfOdd,
- selectCount,
-} from "./counterSlice";
-import styles from "./Counter.module.css";
+import React from 'react'
+import { useSelector, useDispatch } from 'react-redux'
+import { decrement, increment } from './counterSlice'
export function Counter() {
- const count = useSelector(selectCount);
- const dispatch = useDispatch();
- const [incrementAmount, setIncrementAmount] = useState("2");
-
- const incrementValue = Number(incrementAmount) || 0;
+ const count = useSelector((state) => state.counter.value)
+ const dispatch = useDispatch()
return (
<div>
- <div className={styles.row}>
- <button
- className={styles.button}
- aria-label="Decrement value"
- onClick={() => dispatch(decrement())}
- >
- -
- </button>
- <span className={styles.value}>{count}</span>
+ <div>
<button
- className={styles.button}
aria-label="Increment value"
onClick={() => dispatch(increment())}
>
- +
+ Increment
</button>
- </div>
- <div className={styles.row}>
- <input
- className={styles.textbox}
- aria-label="Set increment amount"
- value={incrementAmount}
- onChange={(e) => setIncrementAmount(e.target.value)}
- />
+ <span>{count}</span>
<button
- className={styles.button}
- onClick={() => dispatch(incrementByAmount(incrementValue))}
- >
- Add Amount
- </button>
- <button
- className={styles.asyncButton}
- onClick={() => dispatch(incrementAsync(incrementValue))}
- >
- Add Async
- </button>
- <button
- className={styles.button}
- onClick={() => dispatch(incrementIfOdd(incrementValue))}
+ aria-label="Decrement value"
+ onClick={() => dispatch(decrement())}
>
- Add If Odd
+ Decrement
</button>
</div>
</div>
- );
+ )
}
diff --git a/src/features/counter/Counter.module.css b/src/features/counter/Counter.module.css
deleted file mode 100644
index 9e70f8e..0000000
--- a/src/features/counter/Counter.module.css
+++ /dev/null
@@ -1,78 +0,0 @@
-.row {
- display: flex;
- align-items: center;
- justify-content: center;
-}
-
-.row > button {
- margin-left: 4px;
- margin-right: 8px;
-}
-.row:not(:last-child) {
- margin-bottom: 16px;
-}
-
-.value {
- font-size: 78px;
- padding-left: 16px;
- padding-right: 16px;
- margin-top: 2px;
- font-family: "Courier New", Courier, monospace;
-}
-
-.button {
- appearance: none;
- background: none;
- font-size: 32px;
- padding-left: 12px;
- padding-right: 12px;
- outline: none;
- border: 2px solid transparent;
- color: rgb(112, 76, 182);
- padding-bottom: 4px;
- cursor: pointer;
- background-color: rgba(112, 76, 182, 0.1);
- border-radius: 2px;
- transition: all 0.15s;
-}
-
-.textbox {
- font-size: 32px;
- padding: 2px;
- width: 64px;
- text-align: center;
- margin-right: 4px;
-}
-
-.button:hover,
-.button:focus {
- border: 2px solid rgba(112, 76, 182, 0.4);
-}
-
-.button:active {
- background-color: rgba(112, 76, 182, 0.2);
-}
-
-.asyncButton {
- composes: button;
- position: relative;
-}
-
-.asyncButton:after {
- content: "";
- background-color: rgba(112, 76, 182, 0.15);
- display: block;
- position: absolute;
- width: 100%;
- height: 100%;
- left: 0;
- top: 0;
- opacity: 0;
- transition: width 1s linear, opacity 0.5s ease 1s;
-}
-
-.asyncButton:active:after {
- width: 0%;
- opacity: 1;
- transition: 0s;
-}
diff --git a/src/features/counter/counterAPI.js b/src/features/counter/counterAPI.js
deleted file mode 100644
index cc9b4a4..0000000
--- a/src/features/counter/counterAPI.js
+++ /dev/null
@@ -1,6 +0,0 @@
-// A mock function to mimic making an async request for data
-export function fetchCount(amount = 1) {
- return new Promise((resolve) =>
- setTimeout(() => resolve({ data: amount }), 500)
- );
-}
diff --git a/src/features/counter/counterSlice.js b/src/features/counter/counterSlice.js
index a9441ac..4cb9993 100644
--- a/src/features/counter/counterSlice.js
+++ b/src/features/counter/counterSlice.js
@@ -1,29 +1,10 @@
-import { createAsyncThunk, createSlice } from "@reduxjs/toolkit";
-import { fetchCount } from "./counterAPI";
-
-const initialState = {
- value: 0,
- status: "idle",
-};
-
-// The function below is called a thunk and allows us to perform async logic. It
-// can be dispatched like a regular action: `dispatch(incrementAsync(10))`. This
-// will call the thunk with the `dispatch` function as the first argument. Async
-// code can then be executed and other actions can be dispatched. Thunks are
-// typically used to make async requests.
-export const incrementAsync = createAsyncThunk(
- "counter/fetchCount",
- async (amount) => {
- const response = await fetchCount(amount);
- // The value we return becomes the `fulfilled` action payload
- return response.data;
- }
-);
+import { createSlice } from '@reduxjs/toolkit'
export const counterSlice = createSlice({
- name: "counter",
- initialState,
- // The `reducers` field lets us define reducers and generate associated actions
+ name: 'counter',
+ initialState: {
+ value: 0,
+ },
reducers: {
increment: (state) => {
// Redux Toolkit allows us to write "mutating" logic in reducers. It
@@ -34,40 +15,11 @@ export const counterSlice = createSlice({
},
decrement: (state) => {
state.value -= 1;
- },
- // Use the PayloadAction type to declare the contents of `action.payload`
- incrementByAmount: (state, action) => {
- state.value += action.payload;
- },
- },
- // The `extraReducers` field lets the slice handle actions defined elsewhere,
- // including actions generated by createAsyncThunk or in other slices.
- extraReducers: (builder) => {
- builder
- .addCase(incrementAsync.pending, (state) => {
- state.status = "loading";
- })
- .addCase(incrementAsync.fulfilled, (state, action) => {
- state.status = "idle";
- state.value += action.payload;
- });
+ }
},
-});
-
-export const { increment, decrement, incrementByAmount } = counterSlice.actions;
-
-// The function below is called a selector and allows us to select a value from
-// the state. Selectors can also be defined inline where they're used instead of
-// in the slice file. For example: `useSelector((state: RootState) => state.counter.value)`
-export const selectCount = (state) => state.counter.value;
+})
-// We can also write thunks by hand, which may contain both sync and async logic.
-// Here's an example of conditionally dispatching actions based on current state.
-export const incrementIfOdd = (amount) => (dispatch, getState) => {
- const currentValue = selectCount(getState());
- if (currentValue % 2 === 1) {
- dispatch(incrementByAmount(amount));
- }
-};
+// Action creators are generated for each case reducer function
+export const { increment, decrement } = counterSlice.actions
-export default counterSlice.reducer;
+export default counterSlice.reducer
diff --git a/src/features/counter/counterSlice.spec.js b/src/features/counter/counterSlice.spec.js
deleted file mode 100644
index 113526b..0000000
--- a/src/features/counter/counterSlice.spec.js
+++ /dev/null
@@ -1,33 +0,0 @@
-import counterReducer, {
- increment,
- decrement,
- incrementByAmount,
-} from "./counterSlice";
-
-describe("counter reducer", () => {
- const initialState = {
- value: 3,
- status: "idle",
- };
- it("should handle initial state", () => {
- expect(counterReducer(undefined, { type: "unknown" })).toEqual({
- value: 0,
- status: "idle",
- });
- });
-
- it("should handle increment", () => {
- const actual = counterReducer(initialState, increment());
- expect(actual.value).toEqual(4);
- });
-
- it("should handle decrement", () => {
- const actual = counterReducer(initialState, decrement());
- expect(actual.value).toEqual(2);
- });
-
- it("should handle incrementByAmount", () => {
- const actual = counterReducer(initialState, incrementByAmount(2));
- expect(actual.value).toEqual(5);
- });
-});
diff --git a/src/logo.svg b/src/logo.svg
deleted file mode 100644
index 8466738..0000000
--- a/src/logo.svg
+++ /dev/null
@@ -1 +0,0 @@
-<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 100 100"><g fill="#764ABC"><path d="M65.6 65.4c2.9-.3 5.1-2.8 5-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 1.5.7 2.8 1.6 3.7-3.4 6.7-8.6 11.6-16.4 15.7-5.3 2.8-10.8 3.8-16.3 3.1-4.5-.6-8-2.6-10.2-5.9-3.2-4.9-3.5-10.2-.8-15.5 1.9-3.8 4.9-6.6 6.8-8-.4-1.3-1-3.5-1.3-5.1-14.5 10.5-13 24.7-8.6 31.4 3.3 5 10 8.1 17.4 8.1 2 0 4-.2 6-.7 12.8-2.5 22.5-10.1 28-21.4z"/><path d="M83.2 53c-7.6-8.9-18.8-13.8-31.6-13.8H50c-.9-1.8-2.8-3-4.9-3h-.2c-3.1.1-5.5 2.7-5.4 5.8.1 3 2.6 5.4 5.6 5.4h.2c2.2-.1 4.1-1.5 4.9-3.4H52c7.6 0 14.8 2.2 21.3 6.5 5 3.3 8.6 7.6 10.6 12.8 1.7 4.2 1.6 8.3-.2 11.8-2.8 5.3-7.5 8.2-13.7 8.2-4 0-7.8-1.2-9.8-2.1-1.1 1-3.1 2.6-4.5 3.6 4.3 2 8.7 3.1 12.9 3.1 9.6 0 16.7-5.3 19.4-10.6 2.9-5.8 2.7-15.8-4.8-24.3z"/><path d="M32.4 67.1c.1 3 2.6 5.4 5.6 5.4h.2c3.1-.1 5.5-2.7 5.4-5.8-.1-3-2.6-5.4-5.6-5.4h-.2c-.2 0-.5 0-.7.1-4.1-6.8-5.8-14.2-5.2-22.2.4-6 2.4-11.2 5.9-15.5 2.9-3.7 8.5-5.5 12.3-5.6 10.6-.2 15.1 13 15.4 18.3 1.3.3 3.5 1 5 1.5-1.2-16.2-11.2-24.6-20.8-24.6-9 0-17.3 6.5-20.6 16.1-4.6 12.8-1.6 25.1 4 34.8-.5.7-.8 1.8-.7 2.9z"/></g></svg>
diff --git a/src/main.jsx b/src/main.jsx
index 3139d2e..a7ca55d 100644
--- a/src/main.jsx
+++ b/src/main.jsx
@@ -1,6 +1,6 @@
import React from "react";
import ReactDOM from "react-dom/client";
-import { Provider } from "react-redux";
+import { Provider } from 'react-redux'
import { store } from "./app/store";
import App from "./App";
import "./index.css";