npm install @preact/signals-core
npm install @preact/signals-react
ついでに id 生成の cuid もインストールしておきます
npm install --save @paralleldrive/cuid2
以下をグローバルストアとして公開します
・読み取り専用なtodoのリスト : todoList
・todoを追加する関数 : addTodoFromName()
src/stores/todo.ts
import { createId } from '@paralleldrive/cuid2';
import { signal, computed, ReadonlySignal } from '@preact/signals-react';
interface Todo {
id: string;
name: string;
}
const initialState: Todo[] = [
{
id: 'id001',
name: 'hoge',
},
{
id: 'id002',
name: 'fuga',
},
];
const privateTodoList = signal<Todo[]>(initialState);
const todoList: ReadonlySignal<Todo[]> = computed(() => privateTodoList.value);
const addTodoFromName = (name: string) => {
if (name === '') return;
const newTodo: Todo = {
id: createId(),
name: name,
};
privateTodoList.value = [...privateTodoList.value, newTodo];
};
export { todoList, addTodoFromName };
hooks は登場しません。 import するだけです
src/components/SignalsTodoComponent.tsx
import { FC, useRef } from 'react';
import { todoList, addTodoFromName } from '../stores/todo';
export const SignalsTodoComponent: FC = () => {
const ref = useRef<HTMLInputElement>(null);
const addTodoToList = () => {
if (!ref.current) return;
addTodoFromName(ref.current.value);
ref.current.value = '';
};
return (
<div style={{ border: '1px solid red' }}>
<ul>
{todoList.value.map((v) => {
return (
<li key={`key__${v.id}`}>
({v.id}) : {v.name}
</li>
);
})}
</ul>
<input type="text" ref={ref} />
<button type="button" onClick={addTodoToList}>
追加
</button>
</div>
);
};
ヘッダコンポーネントからストアの値を参照してみます。
src/components/Header.tsx
import { FC } from 'react';
import { todoList } from '../stores/todo';
export const Header: FC = () => {
return <h1>Header Todoの数は({todoList.value.length})です</h1>;
};
src/App.tsx
import './App.css';
import { Header } from './components/Header';
import { SignalsTodoComponent } from './components/SignalsTodoComponent';
function App() {
return (
<>
<Header />
<SignalsTodoComponent />
</>
);
}
export default App;