Skip to content

Instantly share code, notes, and snippets.

@bfollington
Last active May 15, 2020 07:49
Show Gist options
  • Save bfollington/e287ab3f95e121dc94f4c1981a9bc1a6 to your computer and use it in GitHub Desktop.
Save bfollington/e287ab3f95e121dc94f4c1981a9bc1a6 to your computer and use it in GitHub Desktop.
import React, { ChangeEvent } from "react";
import "./App.css";
import { RecoilRoot, atom, useRecoilState } from "recoil";
const useRecoilReducer = <S, A>(
reducer: (s: S, a: A) => S,
recoilState: any
) => {
const [state, setState] = useRecoilState(recoilState);
const dispatch = (a: A) => {
setState(reducer(state, a));
};
return [state, dispatch];
};
type Alignment =
| "lawful good"
| "lawful neutral"
| "lawful evil"
| "neutral good"
| "true neutral"
| "neutral evil"
| "chaotic good"
| "chaotic neutral"
| "chaotic evil";
type ComplexState = {
name: string;
age: number;
alignment: Alignment;
};
type Action =
| { type: "got_older" }
| { type: "changed_name"; payload: string }
| { type: "alignment_shift"; payload: Alignment };
const complexDemoState = atom({
key: "complexDemoState",
default: {
name: "",
age: 0,
alignment: "chaotic neutral",
},
});
const complexDemoReducer = (
state: ComplexState,
action: Action
): ComplexState => {
switch (action.type) {
case "changed_name":
return {
...state,
name: action.payload,
};
case "got_older":
return {
...state,
age: state.age + 1,
};
case "alignment_shift":
return {
...state,
alignment: action.payload,
};
default:
return state;
}
};
const ComplexDemo = () => {
const [state, dispatch] = useRecoilReducer(
complexDemoReducer,
complexDemoState
);
const [name, setName] = React.useState("");
const [alignment, setAlignment] = React.useState<Alignment>(
"chaotic neutral"
);
return (
<div>
<label>Complex Demo</label>
<table>
<tbody>
<tr>
<td>{state.name}</td>
</tr>
<tr>
<td>{state.age}</td>
</tr>
<tr>
<td>{state.alignment}</td>
</tr>
</tbody>
</table>
<button type="button" onClick={() => dispatch({ type: "got_older" })}>
Get Older
</button>
<br />
<input
type="text"
onChange={(e) => setName(e.target.value)}
value={name}
/>
<button
type="button"
onClick={() => dispatch({ type: "changed_name", payload: name })}
>
Change Name
</button>
<br />
<select
onChange={(e) => setAlignment(e.target.value as Alignment)}
value={alignment}
>
<option value="lawful good">lawful good</option>
<option value="lawful neutral">lawful neutral</option>
<option value="lawful evil">lawful evil</option>
<option value="neutral good">neutral good</option>
<option value="true neutral">true neutral</option>
<option value="neutral evil">neutral evil</option>
<option value="chaotic good">chaotic good</option>
<option value="chaotic neutral">chaotic neutral</option>
<option value="chaotic evil">chaotic evil</option>
</select>
<button
type="button"
onClick={() =>
dispatch({ type: "alignment_shift", payload: alignment })
}
>
Update Alignment
</button>
</div>
);
};
function App() {
return (
<RecoilRoot>
<div className="App">
<ComplexDemo />
</div>
</RecoilRoot>
);
}
export default App;
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment