Skip to content

Instantly share code, notes, and snippets.

@Elvecent
Last active October 28, 2019 11:38
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Elvecent/4a85e14ce77bcd83589468ed8b3fd590 to your computer and use it in GitHub Desktop.
Save Elvecent/4a85e14ce77bcd83589468ed8b3fd590 to your computer and use it in GitHub Desktop.
Nice React counter
import { createContext, useContext, useReducer } from "react";
import * as React from "react";
import { render } from "react-dom";
// <LibraryCode>
const StateContext: React.Context<[any, React.Dispatch<any>]> = createContext(
undefined
);
function StateProvider<S, A>({
reducer,
initialState,
children
}: {
reducer: React.Reducer<S, A>;
initialState: S;
children: React.ReactNode;
}) {
return (
<StateContext.Provider value={useReducer(reducer, initialState)}>
{children}
</StateContext.Provider>
);
}
const useStateValue = () => useContext(StateContext);
// </LibraryCode>
type State = {
count: number;
};
type Action = "increment" | "decrement";
const counterReducer = (state: State, action: Action) => {
switch (action) {
case "increment":
return { count: state.count + 1 };
case "decrement":
return { count: state.count - 1 };
default:
return state;
}
};
const Counter = () => {
const [{ count }, dispatch] = useStateValue();
return (
<div>
<h2>{count}</h2>
<button onClick={() => dispatch("increment")}>+1</button>
<button onClick={() => dispatch("decrement")}>-1</button>
</div>
);
};
function App() {
return (
<div>
<StateProvider reducer={counterReducer} initialState={{ count: 0 }}>
<Counter />
</StateProvider>
{/* A second counter with independent state*/}
<StateProvider reducer={counterReducer} initialState={{ count: 0 }}>
<Counter />
</StateProvider>
</div>
);
}
const rootElement = document.getElementById("root");
render(<App />, rootElement);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment