diff --git a/src/App.tsx b/src/App.tsx
index c899da4..761cff9 100644
--- a/src/App.tsx
+++ b/src/App.tsx
@@ -1,26 +1,29 @@
import React from "react";
-import logo from "./logo.svg";
import "./App.scss";
+import { useGlobalState } from "./state/useGlobalState";
+import { UpdateUserName, UpdateUserAge } from "./state/user/UserActions";
function App() {
+ const {state, dispatch} = useGlobalState();
+
+ const updateName = () => {
+ dispatch(new UpdateUserName('Emanuel'))
+ }
+
+ const updateAge = () => {
+ dispatch(new UpdateUserAge(30))
+ }
+
+
return (
-
+
+
+ Current name:
{state.user.name}
+ Current age:
{state.user.age}
);
}
export default App;
+
diff --git a/src/index.tsx b/src/index.tsx
index 3125ee4..fd37a4e 100644
--- a/src/index.tsx
+++ b/src/index.tsx
@@ -3,11 +3,16 @@ import ReactDOM from "react-dom";
import "./index.scss";
import App from "./App";
import * as serviceWorker from "./serviceWorker";
+import { Provider } from "./state/Provider";
+
+
ReactDOM.render(
-
-
- ,
+
+
+
+
+ ,
document.getElementById("root")
);
diff --git a/src/state/Action.ts b/src/state/Action.ts
new file mode 100644
index 0000000..51ae1d2
--- /dev/null
+++ b/src/state/Action.ts
@@ -0,0 +1,3 @@
+export interface Action {
+ readonly type: string;
+}
\ No newline at end of file
diff --git a/src/state/Context.ts b/src/state/Context.ts
new file mode 100644
index 0000000..c23748f
--- /dev/null
+++ b/src/state/Context.ts
@@ -0,0 +1,12 @@
+import React, { createContext } from 'react';
+import { State, initialState } from './State';
+import { Action } from './Action';
+
+
+
+const initialContext: { state: State; dispatch: React.Dispatch } = {
+ state: initialState,
+ dispatch: () => {}
+};
+
+export const Context = createContext(initialContext);
\ No newline at end of file
diff --git a/src/state/Provider.tsx b/src/state/Provider.tsx
new file mode 100644
index 0000000..a388d2c
--- /dev/null
+++ b/src/state/Provider.tsx
@@ -0,0 +1,10 @@
+
+import React, { useReducer } from 'react';
+import { Context } from './Context';
+import { initialState } from './State';
+import { reducer } from './Reducer';
+
+export function Provider({ children }: any) {
+ const [state, dispatch] = useReducer(reducer, initialState);
+ return {children};
+ }
\ No newline at end of file
diff --git a/src/state/Reducer.ts b/src/state/Reducer.ts
new file mode 100644
index 0000000..137e9a3
--- /dev/null
+++ b/src/state/Reducer.ts
@@ -0,0 +1,19 @@
+import { UserReducer } from "./user/UserReducer";
+import { State } from "./State";
+
+export const combineReducers = (reducers: {[P in keyof T]: any}) => {
+ const reducerEntries = Object.entries(reducers) as [keyof T, any][];
+ return (state: T, action: any) => {
+ const nextState = {} as T;
+ for(const [key, reducer] of reducerEntries){
+ const previousStateForKey = state[key];
+ const nextStateForKey = reducer(previousStateForKey, action)
+ nextState[key] = nextStateForKey;
+ }
+ return nextState;
+ }
+}
+
+ export const reducer = combineReducers({
+ user: UserReducer,
+ })
\ No newline at end of file
diff --git a/src/state/State.ts b/src/state/State.ts
new file mode 100644
index 0000000..2cd46e6
--- /dev/null
+++ b/src/state/State.ts
@@ -0,0 +1,9 @@
+import { UserState, initialUserState } from "./user/UserState";
+
+export interface State {
+ user: UserState
+}
+
+export const initialState: State = {
+ user: initialUserState
+}
\ No newline at end of file
diff --git a/src/state/useGlobalState.ts b/src/state/useGlobalState.ts
new file mode 100644
index 0000000..cb7a72d
--- /dev/null
+++ b/src/state/useGlobalState.ts
@@ -0,0 +1,5 @@
+import { useContext } from 'react';
+import { Context } from './Context';
+
+
+export const useGlobalState = () => useContext(Context);
\ No newline at end of file
diff --git a/src/state/user/UserActions.ts b/src/state/user/UserActions.ts
new file mode 100644
index 0000000..3f5fff0
--- /dev/null
+++ b/src/state/user/UserActions.ts
@@ -0,0 +1,22 @@
+import { Action } from "../Action";
+
+export enum UserActionTypes {
+ UpdateUserName = "[User] Update User name",
+ UpdateUserAge = "[User] Update User age"
+
+}
+
+
+
+export class UpdateUserAge implements Action{
+ public readonly type = UserActionTypes.UpdateUserAge;
+ constructor(public age: number) { }
+}
+
+export class UpdateUserName implements Action{
+ public readonly type = UserActionTypes.UpdateUserName;
+ constructor(public name: string) { }
+}
+
+
+export type UserActions = UpdateUserName | UpdateUserAge;
\ No newline at end of file
diff --git a/src/state/user/UserReducer.ts b/src/state/user/UserReducer.ts
new file mode 100644
index 0000000..8e3c525
--- /dev/null
+++ b/src/state/user/UserReducer.ts
@@ -0,0 +1,20 @@
+import { UserActionTypes, UserActions } from "./UserActions";
+import { UserState } from "./UserState";
+
+export const UserReducer = (state: UserState, action: UserActions) => {
+ switch (action.type) {
+ case UserActionTypes.UpdateUserAge:
+ return {
+ ...state,
+ age: action.age
+ };
+ case UserActionTypes.UpdateUserName:
+ return {
+ ...state,
+ name: action.name
+ };
+ default:
+ return state;
+ }
+ };
+
\ No newline at end of file
diff --git a/src/state/user/UserState.ts b/src/state/user/UserState.ts
new file mode 100644
index 0000000..8cf27b7
--- /dev/null
+++ b/src/state/user/UserState.ts
@@ -0,0 +1,10 @@
+export type UserState = {
+ age: number;
+ name: string;
+ };
+
+ export const initialUserState: UserState = {
+ age: 12,
+ name: "Initial name"
+ }
+
\ No newline at end of file