はじめに
この記事は4 React Tips to Instantly Improve Your Codeを日本語に翻訳したものです。リンク先の記事では4つのtipsが紹介されていますが、今日からすぐに使えそうなtipsは3つであるため(一つは初心者が理解するには難しそう)今回は3つ抜粋して紹介します。
興味ある方はぜひ翻訳元の記事を読んでみてください。
Return functions from handlers
まずはこちらのコードをご覧ください。
export default function App() {
const [user, setUser] = useState({
name: "",
surname: "",
address: ""
});
// First handler
const handleNameChange = (e) => {
setUser((prev) => ({
...prev,
name: e.target.value
}));
};
// Second handler!
const handleSurnameChange = (e) => {
setUser((prev) => ({
...prev,
surname: e.target.value
}));
};
// Third handler!!!
const handleAddressChange = (e) => {
setUser((prev) => ({
...prev,
address: e.target.value
}));
};
// What if we need one more input? Should we create another handler for it?
return (
<>
<input value={user.name} onChange={handleNameChange} />
<input value={user.surname} onChange={handleSurnameChange} />
<input value={user.address} onChange={handleAddressChange} />
</>
);
}
どこが改善できるポイントかお分かりいただけたでしょうか?
そう、ポイントはstate
の値を変更するために三つの関数を定義しているところです。
user
のプロパティが例では三つですが、これがメールアドレスや住所など他にも増えるとしたらかなり冗長ですよね。
こういったオブジェクトを更新する関数は実は一つにまとめてDRYに書くことができます。
実際のコードがこちら。
export default function App() {
const [user, setUser] = useState({
name: "",
surname: "",
address: ""
});
const handleInputChange = (field) => {
return (e) => {
setUser((prev) => ({
...prev,
[field]: e.target.value
}));
};
};
return (
<>
<input value={user.name} onChange={handleInputChange("name")} />
<input value={user.surname} onChange={handleInputChange("surname")} />
<input value={user.address} onChange={handleInputChange("address")} />
{JSON.stringify(user)}
</>
);
}
関数が一つにまとめられていてかなりスッキリしましたね。
handleInputChange
のロジックはprev
で現在のuser
の情報を取得し、オブジェクトの中でスプレッド構文を使って展開、その後、引数に渡された該当のfield
キーを更新するという流れです。
React初心者の人はよくやりがちなコードで、私も最初はこのように書いていました。。
Use objects map instead of conditions
続いてのコードはこちらです。
function Account({type}) {
let Component = UsualAccount
if (type === 'vip') {
Component = VipAccount
}
if (type === 'moderator') {
Component = ModeratorAccount
}
if (type === 'admin') {
Component = AdminAccount
}
return (
<div className='account'>
<Component />
<AccountStatistics />
</div>
)
}
こちらもどこが改善できそうか予測できますね。
こちらのコードの改善ポイントは条件分岐です。
ではこのコードをどのようにリファクタできるのか。リファクタ後のコードを見てみましょう。
const ACCOUNTS_MAP = {
'vip': VipAccount,
'usual': UsualAccount,
'admin': AdminAccount,
'moderator': ModeratorAccount,
}
function Account({type}) {
const Component = ACCOUNTS_MAP[type]
return (
<div className='account'>
<Component />
<AccountStatistics />
</div>
)
}
変更箇所はif文を使ってComponent
にエレメントを代入しているのではなく、 オブジェクトを使ってエレメントを代入しているところです。
これも初心者がやってしまいがちな書き方ですね。。
Put independent variables outside of React lifecycle
最後に紹介するtipsはこちらです。
function useItemsList() {
const defaultItems = [1, 2, 3, 4, 5]
const [items, setItems] = useState(defaultItems)
const toggleArrayItem = (arr, val) => {
return arr.includes(val) ? arr.filter(el => el !== val) : [...arr, val];
}
const handleToggleItem = (num) => {
return () => {
setItems(toggleArrayItem(items, num))
}
}
return {
items,
handleToggleItem,
}
}
続いて改善後のコードがこちらです。
const DEFAULT_ITEMS = [
1, 2, 3, 4, 5
]
const toggleArrayItem = (arr, val) => {
return arr.includes(val) ? arr.filter(el => el !== val) : [...arr, val];
}
function useItemsList() {
const [items, setItems] = useState(DEFAULT_ITEMS)
const handleToggleItem = (num) => {
return () => {
setItems(toggleArrayItem(items, num))
}
}
return {
items,
handleToggleItem,
}
}
どこが変更されたのか、なぜその変更がされたのかお分かりいただけましたでしょうか?
まず変更された点に関してはDEFAULT_ITEMS
とtoggleArrayItem
がコンポーネントの外に定義されたところです。
ではなぜ、この変更が行われたのか。
それはライフサイクル、メソッドを必要としない変数や関数をコンポーネントから分離することで依存関係が明確になり、コードリーディングがしやすく、コンポーネントを理解しやすくなると筆者は述べています。
今回の例ではコード量が少ないため、その恩恵を受けることが少ないかもしれませんが、コンポーネントが肥大化すると依存関係が複雑になり、コンポーネントを理解するのが難しくなります。
おわりに
いかがでしたでしょうか?
今回はReact初心者のコードを改善する3つのtipsについて紹介しました。
どれも今日から使えるtipsだと思うのでぜひ、実践してみてください。
今後もこのようなtipsについて紹介していこうと思うのでよければフォロー、いいね、ブックマークよろしくお願いします!