React Reduxに相当するものをhooksでやってみる
Reduxを使わない場合にそれに相当するやつをHooksで実現したいなーって時に考えたやつ
とりあえず完成したやつ
// TODOの型
interface ITodo {
id: number
body: string
isDone: boolean
}
// TODO検索用の型
interface ISearchTodoParams {
body?: string
}
// TODO検索のAPIの代わり
const mockApi = (params?: ISearchTodoParams): Promise<{ todos: ITodo[] }> => {
return new Promise(resolve => {
setTimeout(() => {
resolve({
todos: [
{ id: 1, body: '卵買う', isDone: true },
{ id: 2, body: '塩買う', isDone: false },
{ id: 3, body: '家買う', isDone: false },
],
})
}, 1000)
})
}
// メインディッシュ
export const useTodos = () => {
const [todos, setTodos] = useState<ITodo[]>([])
const [isLoading, setLoading] = useState(false)
const [isError, setError] = useState(false)
const fetchTodos = (params?: ISearchTodoParams) => {
setLoading(true)
// apiの代わり
mockApi(params)
.then(response => {
setTodos(response.todos)
})
.catch(() => {
setError(true)
})
.finally(() => {
setLoading(false)
})
}
return { todos, fetchTodos, isLoading, isError }
}
// 使うとき
export const Todos: FC = () => {
const { todos, fetchTodos } = useTodos()
// 初回取得
useEffect(() => {
fetchTodos()
}, [])
return (
<ul>
<input
type="text"
onChange={e => {
const val = e.target.value
if (val.length === 0) {
return
}
fetchTodos({ body: val })
}}
/>
{todos.map(todo => (
<li>{todo.body}</li>
))}
</ul>
)
}
解説
使うときはこの辺の引数を受け取って使える感じ
/**
* todos: TODOの配列が入ったやつ
* fetchTodos: todoの一覧を取得する関数
* isError: エラーが起きたらtrueになるやつ
* isLoading: 通信中にtrueになるやつ
*/
const { todos, fetchTodos, isError, isLoading } = useTodos()
reducers や actionsとかを書くのと比べると記述量が少なくなってる
Componentが離れたところで参照させたいとかがなければ、これくらいでいいのかなと
reducersやactionを
以上!