My quick implementing of a React screen with La Taverne

Uralys
4 min readFeb 12, 2024

--

Introduction

Previously in AI I explained how I got a JSON from a Google Doc, and how I used AI to accelerate defining my typings.

Today I have to display a Carousel of choices, from this typescript data:

0 — Goal

To have in mind what I’ll explain with code, let’s see the final result immediately:

Now, let’s see how I implemented this screen with React and La Taverne.

1 — Mapping the choices with React

We need to ask the user to pick between choices for every adjective and trait.

Let’s start by listing every keys:

const keysForAdjectives: Array<keyof ProjectAdjectives> = Object.keys(
projectAdjectives
) as Array<keyof ProjectAdjectives>;

const keysForPernaliltyTraits: Array<keyof PersonalityTraits> = Object.keys(
personalityTraits
) as Array<keyof PersonalityTraits>;

Now, we can map over the keys to display both choices:

<>
{keysForAdjectives.map((key: keyof ProjectAdjectives) => (
<>
{projectAdjectives[key].map(adjective => (
<p
key={adjective}
label={adjective}
/>
))}
</>
))}
</>

(Same goes for keysForPernaliltyTraits)

2 — Preparing the state with La Taverne

Before to add the onClick to select the choice, let's prepare the state where to store the selected choices.

La Taverne is a Redux + RTK alternative, based on ImmerJS: the idea is the same: dispatching actions and reducing a global app state.

With La Taverne, the application state is split into feature sub states, called a .

So I go to my user.barrel.ts and add a new action, the one we'll dispatch when the user will select a choice.

Copilot as not learned much about La Taverne so I created a snippet to set actions and reducing quickly:

Thanks to 2 placehoders, I just need to choose a namespace and a PascalCase action name,

Then 2 shortcuts later I have my action almost ready to use:

Let’s type and use the payload in the reducer.

Here I realised I also needed to add these types:

export type ProjectAdjective =
| AvantGardeOrClassic[number]
| CreativeOrConventional[number]
| ModernOrTraditional[number]
| InnovativeOrProven[number]
| MinimalisticOrElaborate[number]
| FunOrSerious[number]
| ElegantOrCasual[number]
| BohemianOrUrban[number];

export type PersonalityTrait =
| AdaptableOrStructured[number]
| CollaborativeOrIndependent[number]
| ProactiveOrReactive[number]
| PerseveringOrFlexible[number]
| ReservedOrExtraverted[number]
| PassionateOrObjective[number]
| PerfectionistOrEfficient[number]
| PositiveOrRealistic[number];

Just a reminder to help you following the types:

And now I can type the payload:

export const PICK_AB_CHOICE = '@@user/PICK_AB_CHOICE';

type PickABChoicePayload = {
key: keyof ProjectAdjectives | keyof PersonalityTraits;
choice: ProjectAdjective | PersonalityTrait;
};

export type PickABChoiceAction = {
type: '@@user/PICK_AB_CHOICE';
payload: PickABChoicePayload;
};

const onPickABChoice = {
on: PICK_AB_CHOICE,
reduce: (state: State, payload: PickABChoicePayload) => {
const {key, choice} = payload;
state.choices[key] = choice;
}
};

So let’s go up to my State to define choices properly:

type ABChoices = SelectedProjectAdjectives & SelectedPersonalityTraits;

type State = {
choices: ABChoices;
}

const initialState: State = {
choices: {}
}

Finally we add the reaction onPickABChoice to the list on my barrel's reactions:

export default {
initialState,
reactions: [
onPickABChoice
]
}

Our app state is ready to handle the user’s choices.

3 — Dispatching the action

Back to our React component, we can now add the onClick to dispatch the action.

First we need the dispatch function and the pour hook to read the state:

import {useTaverne} from 'taverne/hooks';

// ...
// in the Component:

const {dispatch, pour} = useTaverne();
const choices = pour('user.choices');

Let’s write the onClick handler:

const selectAdjective =
(key: keyof ProjectAdjectives, adjective: ProjectAdjective) => () => {
dispatch({
type: PICK_AB_CHOICE,
payload: {key, choice: adjective}
} as PickABChoiceAction);
};

And finally the view can be completed:

<Carousel>
{keysForAdjectives.map((key: keyof ProjectAdjectives) => (
<React.Fragment key={key}>
{projectAdjectives[key].map(adjective => (
<CheckboxWithLabel
key={adjective}
selected={get(key, choices) === adjective}
onClick={selectAdjectives(key, adjective)}
label={t(`adjectives.${adjective}`)}
/>
))}
</React.Fragment>
))}
</Carousel>

4 — Testing the app

Using Redux devtools, we can see the action triggered when we click on a choice:

The state is updated when we click on a choice:

Here is the result again:

Conclusion

That’s my React workflow with La Taverne, starting from google doc.

For next articles I plan to explain La Taverne in simpler terms and examples,

Also I may explain how I created this Carousel with React and Styled Components, or just let me know what you’d want me to cover ?

Thanks for reading, see you around!

Originally published at https://dev.to on February 12, 2024.

--

--

Uralys
0 Followers

Web developer | Music producer | Indie game baker | Keep inspired