1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 1 year has passed since last update.

【今日からできる】React初心者のコードを改善する3つのtips

Posted at

はじめに

この記事は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_ITEMStoggleArrayItemがコンポーネントの外に定義されたところです。

ではなぜ、この変更が行われたのか。
それはライフサイクル、メソッドを必要としない変数や関数をコンポーネントから分離することで依存関係が明確になり、コードリーディングがしやすく、コンポーネントを理解しやすくなると筆者は述べています。

今回の例ではコード量が少ないため、その恩恵を受けることが少ないかもしれませんが、コンポーネントが肥大化すると依存関係が複雑になり、コンポーネントを理解するのが難しくなります。

おわりに

いかがでしたでしょうか?
今回はReact初心者のコードを改善する3つのtipsについて紹介しました。
どれも今日から使えるtipsだと思うのでぜひ、実践してみてください。

今後もこのようなtipsについて紹介していこうと思うのでよければフォロー、いいね、ブックマークよろしくお願いします!

1
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
1
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?