アウトプットのために簡単なカウンターアプリをReact HooksのuseReducerを使用して作成する
本記事はReact初心者がやるReact Hooks -useState編-のカウンターアプリをuseState
からuseReducer
に書き換えたものです。
Coutner.tsxの作成
前回のuseState
と違う点はマイナスの表示は出来ないようにしている
Counter.tsx
import React, { useReducer } from 'react';
import '../index.css';
type State = {
count: number;
};
type Action = { type: 'INCREMENT' } | { type: 'DECREMENT' } | { type: 'RESET' };
const initialCount = {
count: 0,
};
const reducer = (state: State, action: Action) => {
switch (action.type) {
case 'INCREMENT':
return { count: state.count + 1 };
case 'DECREMENT':
return { count: state.count > 0 ? state.count - 1 : 0 };
case 'RESET':
return { count: 0 };
default:
return state;
}
};
const Counter: React.FC = () => {
const [state, dispatch] = useReducer(reducer, initialCount);
return (
<>
<h1>{state.count}</h1>
<button className="plus" onClick={() => dispatch({ type: 'INCREMENT' })}>
+
</button>
<br />
<button className="minus" onClick={() => dispatch({ type: 'DECREMENT' })}>
-
</button>
<br />
<button className="reset" onClick={() => dispatch({ type: 'RESET' })}>
RESET
</button>
</>
);
};
export default Counter;
index.cssの作成
少しボタンをおしゃれにする
index.css
.App {
margin: 0 auto;
text-align: center;
}
.plus {
border: 0;
text-align: center;
display: inline-block;
padding: 14px;
width: 150px;
margin: 7px;
color: #ffffff;
background-color: #36a2eb;
border-radius: 8px;
font-family: 'proxima-nova-soft', sans-serif;
font-weight: 600;
text-decoration: none;
transition: box-shadow 200ms ease-out;
}
.minus {
border: 0;
text-align: center;
display: inline-block;
padding: 14px;
width: 150px;
margin: 7px;
color: #ffffff;
background-color: red;
border-radius: 8px;
font-family: 'proxima-nova-soft', sans-serif;
font-weight: 600;
text-decoration: none;
transition: box-shadow 200ms ease-out;
}
.reset {
border: 0;
text-align: center;
display: inline-block;
padding: 14px;
width: 150px;
margin: 7px;
color: #ffffff;
background-color: gray;
border-radius: 8px;
font-family: 'proxima-nova-soft', sans-serif;
font-weight: 600;
text-decoration: none;
transition: box-shadow 200ms ease-out;
}