Last active
May 30, 2024 18:29
-
-
Save cambiata/8b5c834a7c071ca7c11c8b936f45c9c7 to your computer and use it in GitHub Desktop.
Displays a way to deal with discriminated union types in Solid-js, jsx view as well as store
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import styles from './App.module.css'; | |
import { For, Match, Switch, type Component } from 'solid-js'; | |
import { createStore, SetStoreFunction } from 'solid-js/store'; | |
type Todo = { id: number, text: string, done: boolean }; | |
type TodosStateItems = { s: "Todos", todos: Todo[] }; | |
type TodosState = | |
| { s: 'Empty' } | |
| { s: 'Loading' } | |
| TodosStateItems; | |
const [state, setState] = createStore<TodosState>({ s: 'Empty' }); | |
const setStateItems = setState as SetStoreFunction<TodosStateItems>; // <- setState retyped to use fields from TodosStateItems | |
const toggleTodo = (id: number) => { | |
if (state.s !== 'Todos') return; | |
setStateItems('todos', item => item.id === id, 'done', done => !done); // <- using the retyped setState here! | |
}; | |
const loadTodos = () => { | |
setState({ s: 'Loading' }); | |
setTimeout(() => { | |
setState({ s: 'Todos', todos: [{ id: 1, text: 'Item 1', done: false }, { id: 2, text: 'Item 2', done: true }] }); | |
}, 1000); | |
} | |
const App: Component = () => { | |
return <div class={styles.App}> | |
<header class={styles.header}> | |
<pre>{JSON.stringify(state)}</pre> | |
<button onClick={loadTodos}>Load Items</button> | |
<Switch> | |
<Match when={state.s === 'Empty'}> | |
<h3>Empty - no items</h3> | |
</Match> | |
<Match when={state.s === 'Loading'}> | |
<h3>Loading items...</h3> | |
</Match> | |
<Match when={state.s === 'Todos' && state}> | |
{state => <> | |
<h3>{state().todos.length} Items </h3> | |
<ul> | |
<For each={state().todos}> | |
{todo => <li style={{ cursor: 'pointer' }} onClick={() => toggleTodo(todo.id)}>{todo.text} {JSON.stringify(todo.done)}</li>} | |
</For> | |
</ul> | |
</>} | |
</Match> | |
</Switch> | |
</header> | |
</div> | |
}; | |
export default App; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment