【React】レーティング機能を作る

React

こちらの書籍での学習させていただいた内容をまとめています。

書籍の説明

書籍名: Reactハンズオンラーニング 第2版 ―Webアプリケーション開発のベストプラクティス
著者: Alex Banks 著
出版社: オライリージャパン 発行
発売日: 2021/8/6

starのレーティングを作ります!

目標物はこちら

まずはアイコンを用意します。

アイコンはこちらのreact-iconsを使用します。

React Icons
Include popular icons in your React projects easly with react-icons.

$ npm i react-icons

それではコードを書いていきます。

作成するファイルは3つ。

Appと、StarRatigコンポーネント(親)と、Starコンポーネント(子)。

import React from "react";
import StarRating from "../src/components/StarRating";

function App() {
  return (
    <div>
      <StarRating
        style={{ backgroundColor: "lightblue" }}
        onDoubleClick={(e) => alert("double click")}
      />
    </div>
  );
}

export default App;

StarRatingコンポーネントを表示指定ます。

import React, { useState } from 'react'
import { Star } from './Star'

// ...propsとすることで、全てのpropsを簡単に渡すことができる。
// ただ、この書き方は、propsにはdiv要素がサポートするプロパティのみで、不正なプロパティは含まれていないということを前提として使用する必要がある。
export default function StarRating({ style = {}, totalStars = 5, ...props }) {
  // useStateの実体はstateの初期値を受け取って配列を返す関数。
  const [selectedStars, setSelectedStars] = useState(0)
  return (
    <div style={{ padding: "5px", ...style }} {...props}>
      {[...Array(totalStars)].map((n, i) => (
        <Star
          key={i}
          selected={selectedStars > i}
          onSelect={() => setSelectedStars(i + 1)}
        />
      ))}
      <p>
        {selectedStars} of {totalStars} stars
      </p>
    </div>
  )
}
// starのアイコンがクリックされるたびにStarRatingコンポーネントが再描画される

[…Array(totalStars)]では、totalStarsの数の配列を作成します。この配列は、長さを持つもので、要素の値は持ちません。

mapの引数nはundefinedを、iはインデックスを返します。

…propsによって、App.jsのStarRatingのonDoubleClickイベントハンドラを渡されています。

6行目の…propsはコンポーネントに渡される値を、10行目の…propsはdiv要素に渡されるイベントを意味しています。

import { FaStar } from 'react-icons/fa'

// f => fは、受け取った値をそのまま返すダミー関数
export const Star = ({ selected = false, onSelect = f => f }) => (
  <FaStar color={selected ? "red" : "gray"} onClick={onSelect}/>
)

なぜダミー関数を使うのか?

クリックしたときに、onClick関数がundefinedであればエラーとなるため、それを避けるためにデフォルト引数として使っている。

以上、読んでいただきありがとうございました。

コメント

タイトルとURLをコピーしました