0
0

Reactで評価レート実装

Posted at

Reactで評価レートを実装してみよう。

今回は食べログなど評価アプリでよく見る星を作ってみます!

スクリーンショット 2024-06-05 17.38.46.png

個人でサイトやアプリを作るとき結構使うのではないかなと思ったので参考になれば幸いです。

バージョン

React 18.3.1
TypeScript 4.9.5
tailwindcss 3.4.3
react-icons 5.2.1
node.js 22.2.0
npm 10.7.0

環境構築

まずはお使いのパソコンのターミナルを開いて

.bash
npx create-react-app {アプリ名} --template typescript

TypeScriptを今回は使用していきますがTypeScriptを使用しない場合は

.bash
npx create-react-app {アプリ名}

他にも

Vite

Reactフレームワークを使用する場合

など色々あるのでお好きな方法で環境構築してみましょう

.bash
Success! Created {アプリ名} at /{現在のディレクトリ}/{アプリ名}
Inside that directory, you can run several commands:

  npm start  
    Starts the development server.

  npm run build
    Bundles the app into static files for production.

  npm test
    Starts the test runner.

  npm run eject
    Removes this tool and copies build dependencies, configuration files
    and scripts into the app directory. If you do this, you can’t go back!

We suggest that you begin by typing:

  cd {アプリ名}
  npm start

Happy hacking!

以下のような画面が出てきた場合環境構築は成功です!
cdコマンドを使って命名したアプリ名のフォルダに移動してローカル環境を立ち上げてみましょう。

実装

まずはお使いのターミナルもしくはエディタ上のターミナルで以下のようにローカル環境を立ち上げるコマンドを入力して、下のような画面が表示されることを確認しましょう。

.bash
# npmを使用の場合
npm run start
# yarnを使用の場合
yarn start

スクリーンショット 2024-06-03 11.14.43.png

星マークを表示するファイルの作成と準備

App.tsx
import React from 'react';

function App() {
  return (
    <div>
    </div>
  );
}

export default App;

App.tsxファイルに星マークを表示したいのでdivタグの中を消してしまいましょう!

他にもApp.cssとindex.cssの中身も消しておきましょう!

このApp.tsxファイルに直接星マークを表示しても良いのですが、
複数人で開発する際どのファイルが星を表示させているのかを一目でわかりやすくしたいので星を表示させるだけのファイルを作ります。

src配下にcomponentsフォルダを作成して、さらにそのフォルダ配下に atomsとorganismsという名前のフォルダを作成します。

表示したい画面の機能や規模で表示するファイルを分けることで、複数人で開発するときに分かりやすくします。
スクリーンショット 2024-06-03 11.45.38.png

なぜこのフォルダ名にしたかは下のリンクをご覧ください!
atomicデザイン → 

TailwindCSSとReactIconsのインストール

① TailwindCSSをReactで読み込む

tailwind.config.js
/** @type {import('tailwindcss').Config} */
module.exports = {
  // ドキュメントのコピペを以下のように変更 tsxファイルに適用させる
  content: ["./src/**/*.{js,jsx,ts,tsx}"],
  theme: {
    extend: {},
  },
  plugins: [],
}

② 星のアイコンを外部パッケージで用いる

.bash
# npmを用いる場合
npm install react-icons --save
# yarnを用いる場合
yarn add react-icons

星たちの実装(完成コード)

以上が終わったら、

atomsフォルダ配下にStar.tsxファイルを作成し以下を記述

Star.tsx
import { FC } from "react"
import { FaStar } from "react-icons/fa"

interface Props {
    selected:boolean
    onSelect:() => void
}  

const Star:FC<Props> = (props) => {
    const {selected,onSelect} = props
    return (
        <FaStar color={selected ? "red" : "grey"} onClick={onSelect}/>
    )
}

export default Star

organismsフォルダ配下にStarRates.tsxファイルを作成し以下を記述

StarRates.tsx
import { FC } from "react"
import Star from './atoms/Star'
import { useState } from 'react'

const StarRates:FC = () => {
    const totalStars = 5
    const [selectedStars,setSelectedStars] = useState(3)
    return (
        <div className='flex gap-1 mt-40'>
            {[...Array(totalStars)].map((_,i)=>(
                <Star 
                    key={i} 
                    selected = {selectedStars > i} 
                    onSelect={() => setSelected(i+1)}
                />
            ))}
            <p>
                このお店の評価は {selectedStars} / {totalStars} です!!
            </p>
        </div>
    )
}

export default StarRates

最後にApp.tsxファイルでStarRatesファイルを読み込む

App.tsx
import React from 'react';
import  StarRates  from './components/organisms/StarRates'

function App() {
  return (
    <>
        <StarRates/>
    </>
  );
}

export default App;

解説

コンポーネントの読み込み

App.tsx
import  StarRates  from './components/organisms/StarRates'

コンポーネントの読み込みの際は上記のように書きます、今回はStarRatesファイルで
export default StarRates とあるので、中カッコをつける必要はなくパスさえ合っていれば自由に名前を決める事ができます。

App.tsx
import  Stars  from './components/organisms/StarRates'

function App() {
  return (
    <>
        <Stars/>
    </>
  );
}

export default App;

反対に、export Starrates とある場合は

App.tsx
import  { StarRates }  from './components/organisms/StarRates'

と書きます。

実装手順

StarRates.tsx
import { FC } from "react"
import Star from './atoms/Star'
import { useState } from 'react'

const StarRates:FC = () => {
    const totalStars = 5
    const [selectedStars,setSelectedStars] = useState(3)
    return (
        <div className='flex gap-1 mt-40'>
            {[...Array(totalStars)].map((_,i)=>(
                <Star 
                    key={i} 
                    selected = {selectedStars > i} 
                    onSelect={() => setSelected(i+1)}
                />
            ))}
            <p>
                このお店の評価は {selectedStars} / {totalStars} です!!
            </p>
        </div>
    )
}

export default StarRates

① まず星を最大5つ表示したいので totalStars という定数に5を代入してあげます。
② ユーザー側は点数(数値)で入力することを想定して 
useStateの初期値は3でnumber型にします。
このステートの値が変わるとreactが差分をチェックして再レンダリングをします。
そしてDOMに反映されるという仕組みになっています。

③ ステートの初期値を色に反映させる

{[...Array(totalStars)]
console.log({[...Array(5)])

まず、0をスタートとして中身がundefinedである長さ5である配列を作成します。
これで配列にそれぞれindexを割り振る事ができました。

スクリーンショット 2024-06-03 12.56.10.png

星を5個作成し、それぞれの星に番号を振っていきます。 
この番号を用いて色を後でつけていきます。

{[...Array(totalStars)].map((_,i)=>( 
    <Star key={i}/>
))}

上記で作った番号が振られた配列を展開して、Starコンポーネントに 対応する番号を0から順番に振っていきます。
map関数の第一引数は中身がundefinedなので定義しますが使用しません。
第二引数がindexなのでこれをiと定義します。

keyは配列を展開した際に各々の要素を区別できるように配列の要素ごとに別の値を用意してあげます。
今回はindexにしましたがあまり良くありません、というのも配列の中身が削除されたり中身が入れ替わったりする際意味をなさなくなる可能性があるからです。

そのような場合はuuidなど必ず他と被らない値を用意してくれる外部パッケージなどを用いることが多いです。

このままでは無色の星が5つ表示されているだけなのでstateの点数を画面に反映させます。

StarRates.tsx
{[...Array(totalStars)].map((_,i)=>( 
    <Star 
        key={i}  
        selected={selectedStars > i}
    />
))}
Star.tsx
interface Props {
    selected:boolean
}  

const Star:FC<Props> = (props) => {
    const { selected } = props
    return (
        <FaStar color={selected ? "red" : "grey"} />
    )
}

selectedStarsの値は3なのでiが0、1、2のStarコンポーネントのSelectedがtrueになり、trueの時は星の色が赤色になります。
これで色をつける事ができました。

クリックして評価を変える

StarRates.tsx
{[...Array(totalStars)].map((_,i)=>(
    <Star 
        key={i} 
        selected = {selectedStars > i} 
        onSelect={() => setSelectedStars(i+1)}
    />
))}
Star.tsx
interface Props {
    selected:boolean
    onSelect:() => void
}  

const Star:FC<Props> = (props) => {
    const {selected,onSelect} = props
    return (
        <FaStar color={selected ? "red" : "grey"} onClick={onSelect}/>
    )
}

StarRates(親)からStar(子)にselectedStars(state)を自身のindexより1大きい値にする関数を渡してあげます。

例えば左から2番目の星(評価2にしたい)をクリックした際、クリックされるStarコンポーネントのiは0、1と来ているので1です。 赤色に光る星はselectedStars > i がtrueでなければならないので、この場合はstateの値をi+1してあげればselectedStarsの値は2になりiが0と1のStarコンポーネントの星だけ光ります。
結果として2つ星が光っていることになります。

スクリーンショット 2024-06-05 17.38.46.png

参考文献

0
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
0
0