の続きです。
イベントハンドリング
function handleSubmit(e) {
e.preventDefault();
alert('Hello, world!');
}
<form onSubmit={handleSubmit}>
Reactの例では、上記のようにhandleSubmit関数でe.preventDefault
を実行し、alert
関数を発火させていますが、qwikではこのようにEventで発火させる処理として、直接e.preventDefault
を入れて実行することができません。
以下のように設定します。
Qwikでは非同期のために、イベントハンドラがダウンロードされていません。なので代わりにpreventdefault:{eventName}
属性が存在します。
<form
preventdefault:submit
onSubmit$={() => {
alert("Hello, world")
}
}>
状態の更新
状態の更新には useStore
を使用します。
useStore
は以下のようにObjectを初期値として取ります。
const state = useStore({ count: 0 });
入力したタスクをSubmitした際にalert関数で表示させるようにしてみます。
useStoreでstateを作成し、Formコンポーネントにpropsとして渡します。
import { component$, useStore } from '@builder.io/qwik';
export default component$(() => {
const nameStore = useStore({
name: "",
});
~~~~
<Form nameStore={nameStore} />
そこからonChangeでnameを更新し、onSubmitで表示させます。
import { component$ } from "@builder.io/qwik";
type Form = {
nameStore: any
}
export default component$(({ nameStore }: Form) => {
return (
<form
preventdefault:submit
onSubmit$={() => {
alert(`追加したタスクは、${nameStore.name}です。`)
}
}>
<h2 className="label-wrapper">
<label for="new-todo-input" className="label__lg">
What needs to be done?
</label>
</h2>
<input
type="text"
id="new-todo-input"
className="input input__lg"
name="text"
autoComplete="off"
onChange$={(e) => {
nameStore.name = e.target.value
}}
/>
<button type="submit" className="btn btn__primary btn__lg">
Add
</button>
</form>
)
})
タスク管理用のstate作成
タスク管理用のstateを作成し、それをmockしているデータと置き換えます。
export default component$(() => {
- const DATA = [
- { id: "todo-0", name: "Eat", completed: true },
- { id: "todo-1", name: "Sleep", completed: false },
- { id: "todo-2", name: "Repeat", completed: false },
- ];
+ const taskStore = useStore({
+ name: "",
+ tasks: []
+ });
- { id: "todo-2", name: "Repeat", completed: false },
- ];
+ const taskStore = useStore({
+ name: "",
+ tasks: []
+ });
- const taskList = DATA.map((task) => (
- <Todo id={task.id} name={task.name} completed={task.completed} />
+ const taskList = taskStore.tasks.map((task) => (
+ <Todo id={task.id} name={task.name} completed={task.completed} key={task.id} />
));
return (
<div className="todoapp stack-large">
<h1>TodoMatic</h1>
- <Form />
+ <Form taskStore={taskStore} />
<div className="filters btn-group
import { component$ } from "@builder.io/qwik";
+import { nanoid } from "nanoid";
-export default component$(() => {
+type Form = {
+ taskStore: any
+}
+
+export default component$(({ taskStore }: Form) => {
return (
- <form>
+ <form
+ preventdefault:submit
+ onSubmit$={() => {
+ const newTask = { id: `todo-${nanoid()}`, name: taskStore.name, completed: false };
+ taskStore.tasks = [...taskStore.tasks, newTask]
+ taskStore.name = ""
+ }
+ }>
<h2 className="label-wrapper">
<label for="new-todo-input" className="label__lg">
What needs to be done?
@@ -15,6 +27,10 @@ export default component$(() => {
className="input input__lg"
name="text"
autoComplete="off"
+ value={taskStore.name}
+ onChange$={(e) => {
+ taskStore.name = e.target.value
+ }}
/>
<button type="submit" className="btn btn__primary btn__lg">
Add
ここまで実装するとタスクに自由に追加するところまでできます。
タスク数を表示
タスク数の表示が固定で 3 tasks remaining
になっているのでついでにtaskListをカウントして表示させます。
+ const headingText = `${taskList.length} tasks remaining`;
+
return (
<div className="todoapp stack-large">
<h1>TodoMatic</h1>
@@ -25,7 +27,7 @@ export default component$(() => {
<FilterButton category='Completed' />
</div>
<h2 id="list-heading">
- 3 tasks remaining
+ {headingText}
</h2>
<ul
role="list"
明日も引き続きやっていきます。