From 88de79086eedfe573064310c2661cc4eafb252c6 Mon Sep 17 00:00:00 2001 From: e560248 Date: Tue, 8 Apr 2025 13:28:46 +0200 Subject: [PATCH] add immerJs example --- react-advanced-tag1/package-lock.json | 11 +++++ react-advanced-tag1/package.json | 3 +- react-advanced-tag1/src/App.tsx | 2 + .../common/components/Header/Navigation.tsx | 3 ++ .../exercises/ImmerExercise/index.tsx | 44 +++++++++++++++++++ .../exercises/RefExercise/index.tsx | 2 + react-advanced-tag1/src/main.tsx | 3 ++ react-advanced-tag1/src/pages/ImmerPage.tsx | 10 +++++ 8 files changed, 77 insertions(+), 1 deletion(-) create mode 100644 react-advanced-tag1/src/common/components/exercises/ImmerExercise/index.tsx create mode 100644 react-advanced-tag1/src/pages/ImmerPage.tsx diff --git a/react-advanced-tag1/package-lock.json b/react-advanced-tag1/package-lock.json index fae4452..658bdbf 100644 --- a/react-advanced-tag1/package-lock.json +++ b/react-advanced-tag1/package-lock.json @@ -8,6 +8,7 @@ "name": "react-advanced-tag1", "version": "0.0.0", "dependencies": { + "immer": "^10.1.1", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^7.5.0", @@ -3465,6 +3466,16 @@ "node": ">= 4" } }, + "node_modules/immer": { + "version": "10.1.1", + "resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/immer/-/immer-10.1.1.tgz", + "integrity": "sha512-s2MPrmjovJcoMaHtx6K11Ra7oD05NT97w1IC5zpMkT6Atjr7H8LjaDd81iIxUYpMKSRRNMJE703M1Fhr/TctHw==", + "license": "MIT", + "funding": { + "type": "opencollective", + "url": "https://opencollective.com/immer" + } + }, "node_modules/import-fresh": { "version": "3.3.1", "resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/import-fresh/-/import-fresh-3.3.1.tgz", diff --git a/react-advanced-tag1/package.json b/react-advanced-tag1/package.json index 0d9f79d..0d6734a 100644 --- a/react-advanced-tag1/package.json +++ b/react-advanced-tag1/package.json @@ -17,6 +17,7 @@ "prettier": "prettier ./src --write" }, "dependencies": { + "immer": "^10.1.1", "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^7.5.0", @@ -42,4 +43,4 @@ "vite": "^6.2.0", "vitest": "^3.1.1" } -} \ No newline at end of file +} diff --git a/react-advanced-tag1/src/App.tsx b/react-advanced-tag1/src/App.tsx index e6f4c04..b23f5b7 100644 --- a/react-advanced-tag1/src/App.tsx +++ b/react-advanced-tag1/src/App.tsx @@ -11,6 +11,7 @@ import ComponentWrapperPage from './pages/ComponentWrapperPage' import ZustandCounterPage from './pages/ZustandCounterPage' import ModalPage from './pages/ModalPage' import { HocPage } from './pages/HocPage' +import ImmerPage from './pages/ImmerPage' function App() { return ( @@ -25,6 +26,7 @@ function App() { } /> } /> } /> + } /> ) diff --git a/react-advanced-tag1/src/common/components/Header/Navigation.tsx b/react-advanced-tag1/src/common/components/Header/Navigation.tsx index c9efe35..bc17736 100644 --- a/react-advanced-tag1/src/common/components/Header/Navigation.tsx +++ b/react-advanced-tag1/src/common/components/Header/Navigation.tsx @@ -29,6 +29,9 @@ export default function Navigation() {
  • HOC
  • +
  • + Immer +
  • ) diff --git a/react-advanced-tag1/src/common/components/exercises/ImmerExercise/index.tsx b/react-advanced-tag1/src/common/components/exercises/ImmerExercise/index.tsx new file mode 100644 index 0000000..135ea56 --- /dev/null +++ b/react-advanced-tag1/src/common/components/exercises/ImmerExercise/index.tsx @@ -0,0 +1,44 @@ +import { produce } from 'immer' +import { useState } from 'react' + +export default function ImmerExercise() { + const [user, setUser] = useState({ + name: 'Alice', + + address: { + city: 'Wonderland', + + zip: '12345', + }, + }) + + const updateUser = () => { + // this is "normal" way to update state in objects + setUser((prevUser) => ({ + ...prevUser, + address: { + ...prevUser.address, + city: 'New Wonderland', + }, + })) + } + + const updateUserWithImmer = () => { + // immer way + setUser((prevUser) => + produce(prevUser, (draft) => { + draft.address.city = 'New Wonderland' + }) + ) + } + + return ( + <> +

    + {user.address.city}: {user.name} +

    + + + + ) +} diff --git a/react-advanced-tag1/src/common/components/exercises/RefExercise/index.tsx b/react-advanced-tag1/src/common/components/exercises/RefExercise/index.tsx index 119c0e6..345d4dd 100644 --- a/react-advanced-tag1/src/common/components/exercises/RefExercise/index.tsx +++ b/react-advanced-tag1/src/common/components/exercises/RefExercise/index.tsx @@ -44,9 +44,11 @@ export default function RefExercise(): React.ReactElement { } const handleChangeSubmit = () => { + // This is a bad way to handle form submission const strasse = document.querySelector( 'input[name="strasse"]' ) as HTMLInputElement + // This is a bad way to handle form submission const city = document.querySelector( 'input[name="city"]' ) as HTMLInputElement diff --git a/react-advanced-tag1/src/main.tsx b/react-advanced-tag1/src/main.tsx index 2b21104..2f3635f 100644 --- a/react-advanced-tag1/src/main.tsx +++ b/react-advanced-tag1/src/main.tsx @@ -3,6 +3,9 @@ import { createRoot } from 'react-dom/client' import './index.css' import App from './App.tsx' import { BrowserRouter } from 'react-router-dom' +import { enableMapSet } from 'immer' + +enableMapSet() createRoot(document.getElementById('root')!).render( diff --git a/react-advanced-tag1/src/pages/ImmerPage.tsx b/react-advanced-tag1/src/pages/ImmerPage.tsx new file mode 100644 index 0000000..05aeaed --- /dev/null +++ b/react-advanced-tag1/src/pages/ImmerPage.tsx @@ -0,0 +1,10 @@ +import ComponentWrapper from '../common/components/ComponentWrapper/ComponentWrapper' +import ImmerExercise from '../common/components/exercises/ImmerExercise' + +export default function ImmerPage() { + return ( + + + + ) +}