This series of articles focuses on building a full-stack app with the following technology stack: PlanetScale - Prisma - tRPC - React. The project name is mythica and it will allow users to collect random mythical creatures. Here is the full list of the articles:
- Part One
- Part Two
- Part Three
- Part Four
- Part Five <— You are here
Table of contents
Open Table of contents
Overview
In this article we will be finalizing our Mythica series by adding the game logic with the aid of OvermindJS. Basically, we want the user to be able to hunt a creature by clicking on the heart icon, we will store user selections in our app state’s huntedCreatures
array, which contains the id
s of all selections made by user. Another piece of state is won
attribute which is set to true
if the user managed to hunt 5 unique creatures, the user keeps playing until they reach this number however if they pick the same creature in the same run, this creature is removed from the list.
1. Adding OvermindJS app state
In client/src
directory add state.ts
file with the following content.
import { IContext, createOvermind, derived } from "overmind";
import { StateHook, createActionsHook, createStateHook } from "overmind-react";
type State = {
state: {
huntedCreatures: Array<number>; // list of ids of hunted creatures
won: boolean;
len: number;
};
};
export const useAppState = createStateHook() as StateHook<IContext<State>>;
export const useAction = createActionsHook();
export const appState = createOvermind({
state: {
huntedCreatures: [],
len: 0,
won: false,
},
actions: {
huntCreature({ state }: State, creatureId: number) {
console.log(creatureId);
if (state.huntedCreatures.includes(creatureId)) {
state.huntedCreatures = state.huntedCreatures.filter(
id => id != creatureId
);
state.len--;
} else {
state.huntedCreatures.push(creatureId);
state.len++;
}
if (state.len == 5) {
state.won = true;
state.huntedCreatures = [];
state.len = 0;
}
console.log({ len: state.len });
console.log(state.huntedCreatures);
},
},
});
State
type contain different pieces of state in our app like so:
huntedCreatures
list ofid
s of the creatures the user hunted.won
to determine if user has collected exactly ann
number of unique creatures, which is hardcoded for now to 5.
2. Provide state
to the entire app
Inside App.tsx
we need to wrap the entire app with Provider
from overmind
and provide our appState
to it like so
<Provider value={appState}>...</Provider>
3. GameResult
Component
We have a very simple UI to view the result of the game by consuming our appState
import { useAppState } from "../state";
export const GameResult = () => {
const { len, won } = useAppState(state => state);
return (
<>
<p>{len}</p>
<p>{won ? "You won" : ""}</p>
</>
);
};
4. Hunt Action
We want a creature to be hunted when the heart icon is pressed. So we execute our huntCreature
action and then refetch
a new creature.
<IconHeart
onClick={() => {
actions.huntCreature(creature.id);
response.refetch();
}}
size="1.1rem"
className={classes.like}
stroke={1.5}
/>
And that is it we have finalized the game logic and it is working pretty nice now.
Conclusion
In this tutorial we learned how to use OvermindJS for state management.