diff --git a/react-advanced-tag1/package-lock.json b/react-advanced-tag1/package-lock.json index 87017f4..ec30ece 100644 --- a/react-advanced-tag1/package-lock.json +++ b/react-advanced-tag1/package-lock.json @@ -11,7 +11,8 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^7.5.0", - "react-scan": "^0.3.3" + "react-scan": "^0.3.3", + "zustand": "^5.0.3" }, "devDependencies": { "@eslint/js": "^9.21.0", @@ -6048,6 +6049,35 @@ "funding": { "url": "https://github.com/sponsors/sindresorhus" } + }, + "node_modules/zustand": { + "version": "5.0.3", + "resolved": "https://bin.sbb.ch/artifactory/api/npm/npm/zustand/-/zustand-5.0.3.tgz", + "integrity": "sha512-14fwWQtU3pH4dE0dOpdMiWjddcH+QzKIgk1cl8epwSE7yag43k/AD/m4L6+K7DytAOr9gGBe3/EXj9g7cdostg==", + "license": "MIT", + "engines": { + "node": ">=12.20.0" + }, + "peerDependencies": { + "@types/react": ">=18.0.0", + "immer": ">=9.0.6", + "react": ">=18.0.0", + "use-sync-external-store": ">=1.2.0" + }, + "peerDependenciesMeta": { + "@types/react": { + "optional": true + }, + "immer": { + "optional": true + }, + "react": { + "optional": true + }, + "use-sync-external-store": { + "optional": true + } + } } } } diff --git a/react-advanced-tag1/package.json b/react-advanced-tag1/package.json index deaeac4..9bf392e 100644 --- a/react-advanced-tag1/package.json +++ b/react-advanced-tag1/package.json @@ -19,7 +19,8 @@ "react": "^19.0.0", "react-dom": "^19.0.0", "react-router-dom": "^7.5.0", - "react-scan": "^0.3.3" + "react-scan": "^0.3.3", + "zustand": "^5.0.3" }, "devDependencies": { "@eslint/js": "^9.21.0", @@ -39,4 +40,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 8742d80..34f3776 100644 --- a/react-advanced-tag1/src/App.tsx +++ b/react-advanced-tag1/src/App.tsx @@ -8,6 +8,7 @@ import EffectExercisesPage from './routes/EffectExercisesPage' import FormsPage from './routes/FormsPage' import MemoCallbackPage from './routes/MemoCallbackPage' import ComponentWrapperPage from './routes/ComponentWrapperPage' +import ZustandCounterPage from './routes/ZustandCounterPage' function App() { @@ -19,7 +20,7 @@ function App() { } /> } /> } /> - + } /> } diff --git a/react-advanced-tag1/src/common/components/ComponentWrapper/ComponentWrapper.tsx b/react-advanced-tag1/src/common/components/ComponentWrapper/ComponentWrapper.tsx index e4f89f1..d27d829 100644 --- a/react-advanced-tag1/src/common/components/ComponentWrapper/ComponentWrapper.tsx +++ b/react-advanced-tag1/src/common/components/ComponentWrapper/ComponentWrapper.tsx @@ -5,7 +5,7 @@ interface ComponentWrapperProps { children: React.ReactNode; } export default function ComponentWrapper({ children, title }: ComponentWrapperProps): React.ReactElement { - console.log("ComponentWrapper rendered"); + console.log("ComponentWrapper rendered:", title); return (
{title &&

{title}

} diff --git a/react-advanced-tag1/src/common/components/Header/Navigation.tsx b/react-advanced-tag1/src/common/components/Header/Navigation.tsx index 4f78402..ef8ceea 100644 --- a/react-advanced-tag1/src/common/components/Header/Navigation.tsx +++ b/react-advanced-tag1/src/common/components/Header/Navigation.tsx @@ -8,6 +8,7 @@ export default function Navigation () {
  • Forms
  • Memo und Callback
  • Component Wrapper
  • +
  • ZustandCounterPage
  • ); } \ No newline at end of file diff --git a/react-advanced-tag1/src/common/stores/counter-store.ts b/react-advanced-tag1/src/common/stores/counter-store.ts new file mode 100644 index 0000000..862d617 --- /dev/null +++ b/react-advanced-tag1/src/common/stores/counter-store.ts @@ -0,0 +1,15 @@ +import { create } from "zustand"; + +interface CounterState { + count: number; + increment: () => void; + decrement: () => void; +} + +const useCounterStore = create((set) => ({ + count: 0, + increment: () => set((state) => ({ count: state.count + 1 })), + decrement: () => set((state) => ({ count: state.count - 1 })), +})); + +export default useCounterStore; \ No newline at end of file diff --git a/react-advanced-tag1/src/routes/ComponentWrapperPage.tsx b/react-advanced-tag1/src/routes/ComponentWrapperPage.tsx index aa54a17..8572513 100644 --- a/react-advanced-tag1/src/routes/ComponentWrapperPage.tsx +++ b/react-advanced-tag1/src/routes/ComponentWrapperPage.tsx @@ -4,6 +4,7 @@ import Modal from "../common/components/Modal"; import { useState } from "react"; export default function ComponentWrapperPage() { + const [modalOpen, setModalOpen] = useState(false); return (
    diff --git a/react-advanced-tag1/src/routes/ZustandCounterPage.tsx b/react-advanced-tag1/src/routes/ZustandCounterPage.tsx new file mode 100644 index 0000000..281ef58 --- /dev/null +++ b/react-advanced-tag1/src/routes/ZustandCounterPage.tsx @@ -0,0 +1,18 @@ +import ComponentWrapper from "../common/components/ComponentWrapper/ComponentWrapper"; +import useCounterStore from "../common/stores/counter-store"; + +export default function ZustandCounterPage() { + const {decrement, increment} = useCounterStore(); + return ( + + + + + + ); +} + +function CounterValue() { + const count = useCounterStore((state) => state.count); + return

    Count: {count}

    ; +} \ No newline at end of file