Skip to content

Commit

Permalink
fix internal error
Browse files Browse the repository at this point in the history
  • Loading branch information
MrWangJustToDo committed Dec 7, 2023
1 parent a2bb962 commit 8e44386
Show file tree
Hide file tree
Showing 4 changed files with 207 additions and 2 deletions.
4 changes: 4 additions & 0 deletions app/.vitepress/config.mts
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,10 @@ export default defineConfig({
{ text: "Create State", link: "/createState" },
],
},
{
text: "Example",
items: [{ text: "TodoList", link: "/todoList" }],
},
{
text: "TODO",
},
Expand Down
148 changes: 148 additions & 0 deletions app/.vitepress/theme/components/todoList.vue
Original file line number Diff line number Diff line change
@@ -0,0 +1,148 @@
<script lang="ts" setup>
import { onBeforeUnmount, onMounted, ref } from 'vue';
import { createState } from 'reactivity-store';
import { createElement, useState } from 'react';
import ReactDOM from 'react-dom/client';
const useTodo = createState(() => ({
data: [
{ id: 1, text: 'todo 1', done: false, edit: false },
{ id: 2, text: 'todo 2', done: false, edit: false },
{ id: 3, text: 'todo 3', done: false, edit: false },
],
}), {
withDeepSelector: false,
withNamespace: 'useTodo',
withPersist: 'todo-list',
withActions: (s: { data: { id: number; text: string; done: boolean; edit: boolean; }[]; }) => ({
addTodo: (text: string) => {
s.data.push({ id: s.data.length + Math.random(), text, done: false, edit: false });
},
removeTodo: (id: number) => {
s.data = s.data.filter((todo) => todo.id !== id);
},
toggleTodo: (id: number) => {
s.data = s.data.map((todo) => {
if (todo.id === id) {
todo.done = !todo.done;
}
return todo;
});
},
toggleEdit: (id: number) => {
s.data = s.data.map((todo) => {
if (todo.id === id) {
todo.edit = !todo.edit;
} else {
todo.edit = false;
}
return todo;
});
},
editTodo: (id: number, content: string) => {
s.data = s.data.map((todo) => {
if (todo.id === id) {
todo.text = content;
}
return todo;
});
}
})
});
const divRef = ref<HTMLDivElement>();
const Item = ({ id }: { id: number }) => {
const { data, toggleTodo, toggleEdit, removeTodo, editTodo } = useTodo.useShallowSelector();
const todo = data.find((todo) => todo.id === id);
if (!todo) {
return null;
}
return createElement('li', null,
createElement('div', { style: { display: 'inline-flex', width: '60%' } }, createElement('input', { type: 'checkbox', checked: todo.done, onChange: () => toggleTodo?.(todo.id) }),
todo.edit ? (
createElement('input', { type: 'text', autoFocus: true, value: todo.text, onChange: (e: { target: { value: string; }; }) => editTodo?.(todo.id, e.target.value) })
) : (
createElement('span', null, todo.text)
))
,
createElement('div', null,
createElement('button', { onClick: () => toggleEdit?.(todo.id) }, todo.edit ? 'Done' : 'Edit'),
createElement('button', { style: { marginLeft: '10px' }, onClick: () => removeTodo?.(todo.id) }, 'Remove'),
)
)
}
const App = () => {
const { data, addTodo } = useTodo.useShallowSelector();
const [v, setV] = useState('')
return createElement('div', { style: { border: '1px solid', borderRadius: '2px', padding: '8px' } },
createElement('h1', { style: { padding: '2px', textAlign: 'center' } }, 'Todo List'),
createElement('div', { style: { padding: '2px', textAlign: 'center', margin: '8px' } },
createElement('span', null, 'Total: '),
createElement('span', { style: { color: 'red' } }, data.length),
createElement('span', null, ' Done: '),
createElement('span', { style: { color: 'red' } }, data.filter((todo: { done: boolean; }) => todo.done).length),
createElement('span', null, ' Undone: '),
createElement('span', { style: { color: 'red' } }, data.filter((todo: { done: boolean; }) => !todo.done).length),
),
createElement('div', { style: { display: 'flex', justifyContent: 'space-around' } },
createElement('input', { placeholder: 'input', value: v, onChange: (e) => setV(e.target.value), style: { border: '1px solid', padding: '2px', borderRadius: '2px', width: '50%' } }),
createElement('button', { onClick: () => { addTodo(v), setV('') }, style: { border: '1px solid', borderRadius: '4px', padding: '5px 10px' } }, 'Add')
),
createElement('ul', null, data.map((todo: { id: number; text: string; done: boolean; edit: boolean; }) => (
createElement(Item, { id: todo.id, key: todo.id })
))),
// createElement('button', { onClick: () => addTodo?.('New Todo') }, 'Add Todo'),
);
}
let root: ReturnType<(typeof ReactDOM)["createRoot"]> | null = null;
onMounted(() => {
root = ReactDOM.createRoot(divRef.value as HTMLElement);
root.render(createElement(App));
});
onBeforeUnmount(() => {
root?.unmount();
});
</script>

<template>
<div ref="divRef"></div>
</template>

<style>
.todo-list {
border: 1px solid;
border-radius: 2px;
padding: 8px;
}
button {
border: 1px solid;
border-radius: 4px;
padding: 5px 10px;
}
input:not([type=checkbox]) {
border: 1px solid;
padding: 2px;
border-radius: 2px;
width: 50%;
}
li {
display: flex;
justify-content: space-between;
align-items: center;
}
</style>
52 changes: 52 additions & 0 deletions app/todoList.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,52 @@
## ToDoList example

```tsx
import { createState } from 'reactivity-store';

const useTodo = createState(() => ({
data: [],
}), {
withActions: (s: { data: { id: number; text: string; done: boolean; edit: boolean; }[]; }) => ({
addTodo: (text: string) => {
s.data.push({ id: s.data.length + Math.random(), text, done: false, edit: false });
},
removeTodo: (id: number) => {
s.data = s.data.filter((todo) => todo.id !== id);
},
toggleTodo: (id: number) => {
s.data = s.data.map((todo) => {
if (todo.id === id) {
todo.done = !todo.done;
}
return todo;
});
},
toggleEdit: (id: number) => {
s.data = s.data.map((todo) => {
if (todo.id === id) {
todo.edit = !todo.edit;
} else {
todo.edit = false;
}
return todo;
});
},
editTodo: (id: number, content: string) => {
s.data = s.data.map((todo) => {
if (todo.id === id) {
todo.text = content;
}
return todo;
});
}
})
});
```

## Example

<script setup>
import Todo from '@theme/components/todoList.vue'
</script>

<Todo />
5 changes: 3 additions & 2 deletions packages/r-store/src/shared/hook.ts
Original file line number Diff line number Diff line change
Expand Up @@ -84,7 +84,7 @@ export const createHook = <T extends Record<string, unknown>, C extends Record<s
const selectorRef = useSubscribeCallbackRef(selector, deepSelector);

const getSelected = useCallbackRef((i?: Controller) => {
if (deepSelector) i?.run?.();
i?.run?.();
// 0.1.9
// make the returned value as a readonly value, so the only way to change the state is in the `actions` middleware
if (selector) {
Expand Down Expand Up @@ -236,7 +236,8 @@ export const createHook = <T extends Record<string, unknown>, C extends Record<s

const selectorRef = useSubscribeCallbackRef(selector, false);

const getSelected = useCallbackRef(() => {
const getSelected = useCallbackRef((i?: Controller) => {
i?.run?.();
if (selector) {
ref.current = selector({ ...readonlyState, ...actions });
} else {
Expand Down

0 comments on commit 8e44386

Please sign in to comment.