反応星の反応


評価星は、評価システムを実装するほとんどのアプリケーションで使用される古典的なUIコンポーネントです.この記事では、それがどのように行われるかを見るつもりです.
次のGIFはこのチュートリアルの最終結果を表示します😊.

あなたがまっすぐに最終的なコードにジャンプする場合は、すべての説明をスキップすることができますし、記事の最後に取得します.
まず、コンポーネントフォルダを作成しますsrc フォルダ、コンポーネントフォルダを保持するRatingStars.jsStar.js ファイル.CSSについてはstyle.css インポートされるファイルApp.js コンポーネントstyle.css ファイルはsrc フォルダと必要なすべてのCSSルールが含まれます.
RatingStars コンポーネントは、5つの評価グレードを必要とするので、これらの等級を文字列として格納するために配列を使用しました.
const GRADES = ['Poor', 'Fair', 'Good', 'Very good', 'Excellent'];
RatingStars コンポーネント、私はGRADES すべての値について星を表示する配列と、各値のインデックスをStar コンポーネント.のためにkey プロップ、私は成績を過ぎた.
ドキュメントで述べたように

Keys help React identify which items have changed, are added, or are removed. Keys should be given to the elements inside the array to give the elements a stable identity.


あなたがより多くを読んで欲しいならばkey prop .
The h1 ユーザーによって行われたレビューの結果を表示するためのものです.
また、後で書く予定のCSSクラスも追加しました.
import React from 'react';
import Star from './Star';

const RatingStars = () => {
    const GRADES = ['Poor', 'Fair', 'Good', 'Very good', 'Excellent'];

    return (
        <div className="container">
            <h1 className="result"></h1>
            <div className="stars">
                {
                    GRADES.map((grade, index) => (
                        <Star 
                            index={index} 
                            key={grade}
                        />
                    ))
                }
            </div>
        </div>
    );
}

export default RatingStars;
さあ、作ってみましょうstar コンポーネントは、私はスターSVGiconsvg .
私は等級のインデックスを持っているラジオボタンでGRADES 値を配列とし、ラベル要素によってSVG要素とラジオ入力要素をグループ化します.
import React from 'react';

const Star = (props) => {

    return (
        <label className="star">
            <input
                type="radio"
                name="rating"
                id={props.grade}
                value={props.index}
                className="stars_radio-input"
            />
            <svg 
                width="58" 
                height="58" 
                viewBox="0 0 24 24" 
                fill="none" 
                stroke="#393939" 
                strokeWidth="1" 
                strokeLinecap="round" 
                strokeLinejoin="round" 
            >
                <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
            </svg>
        </label>
    );
}

export default Star;
これまで、これは我々のアプリのように見えます:

今、それをきれいにする時間です.インサイドstyles.css file以下のクラスを書きます:
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}
私たちは、パディングとマージンをリセットするためにユニバーサルセレクタを使用しており、また、私たちのサイズの要素を助けるのボックスボックスとしてボックスのサイズを設定します.このプロパティの詳細についてはthe MDN web docs
.container {
  padding: 16px;
  margin: 16px auto;
}
The .container クラスはスペースの面倒を見ます.
.result {
  text-align: center;
  margin-bottom: 16px;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}
The .result クラスを適用するh1 中で要素RatingStars コンポーネント.
.stars {
  display: flex;
  justify-content: center;
  gap: 8px;
}
星を包む星のクラスについてflex ディスプレイの値を適切に、フレックス項目(星)を水平方向に表示されますgap 各々の星の間の8 pxの.
.star {
  position: relative;
  cursor: pointer;
}
あらゆる星のために、我々は星がクリックされるユーザーにinsinuateするためにポインタ・カーソルを加えました.地位relative 私たちは後でラジオボタンを配置するのを助けるつもりです.
.stars_radio-input {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  clip: rect(1px, 1px, 1px, 1px);
}
これは視覚的にラジオボタンを隠すつもりです.
.stars_radio-input:checked ~ svg {
  fill: yellow;
}
これは、星がチェックされたかどうか確認するために使用する仮のクラスです.
我々は評価結果を表示するためにRatingStar コンポーネントは、子コンポーネントからの状態をStar.js を返します.RatingStar.js .
リージョン状態についてもっと読みたい場合はReact Docs
この作業を開始するには、親コンポーネントの状態を宣言する必要があります.
const [gradeIndex, setGradeIndex] = useState();
これは親コンポーネントの状態を設定するための関数であり、子コンポーネントにプロップとして渡すことになります.
    const changeGradeIndex = ( index ) => {
        setGradeIndex(index);
    }
そして、これは我々が使用する予定ですStar.js 親コンポーネントの状態を更新するコンポーネント.
const changeGrade = (e) => {
        props.changeGrade(e.target.value);
    }
また、添付しますonClick ラジオボタンのイベントStar.js それはchangeGrade 関数.
onClick={changeGrade}
インサイドH 1インRatingStars.js コンポーネントは、状態を定義するときにのみ状態の値を表示するために三項演算子を使用します.
<h1 className="result">
   { GRADES[gradeIndex] ? GRADES[gradeIndex] : 'You didn\'t review yet'}
</h1>
さて、これは我々のアプリがどのように見えるかです

それは古典的な星の評価UIコンポーネントのように動作するように、我々は色を動的に星に黄色を追加する必要があります.
the activeStar オブジェクトが宣言され、RatingStars .
const activeStar = {
        fill: 'yellow'
    };
それから、それを柱に支柱として渡してくださいStar.js , 我々はまた、色の黄色を持って左から始まる前の星に沿ってクリック星をしたいだけので、ここで三項演算子を使用しました.
style={ gradeIndex > index ? activeStar : {}}
スタイル属性をSVG要素に加えてください.
<svg
   width="58" 
   height="58" 
   viewBox="0 0 24 24" 
   fill="none" 
   stroke="#393939" 
   strokeWidth="1" 
   strokeLinecap="round" 
   strokeLinejoin="round" 
   style={props.style}
>
を削除することを忘れないでください.stars_radio-input:checked ~ svg からstyle.css , 我々がもうそれを必要としない時から.
最後に、これはコード全体です:src\components\RatingStars.js
import React, { useState } from 'react';
import Star from './Star';

const RatingStars = () => {
    const [gradeIndex, setGradeIndex] = useState();
    const GRADES = ['Poor', 'Fair', 'Good', 'Very good', 'Excellent'];
    const activeStar = {
        fill: 'yellow'
    };

    const changeGradeIndex = ( index ) => {
        setGradeIndex(index);
    }

    return (
        <div className="container">
            <h1 className="result">{ GRADES[gradeIndex] ? GRADES[gradeIndex] : 'You didn\'t review yet'}</h1>
            <div className="stars">
                {
                    GRADES.map((grade, index) => (
                        <Star 
                            index={index} 
                            key={grade} 
                            changeGradeIndex={changeGradeIndex}
                            style={ gradeIndex > index ? activeStar : {}}
                        />
                    ))
                }
            </div>
        </div>
    );
}

export default RatingStars;
src\components\Star.js
import React from 'react';

const Star = (props) => {

    const changeGrade = (e) => {
        props.changeGradeIndex(e.target.value);
    }

    return (
        <label className="star">
            <input
                type="radio"
                name="rating"
                id={props.grade}
                value={props.index}
                className="stars_radio-input"
                onClick={changeGrade}
            />
            <svg 
                width="58" 
                height="58" 
                viewBox="0 0 24 24" 
                fill="none" 
                stroke="#393939" 
                strokeWidth="1" 
                strokeLinecap="round" 
                strokeLinejoin="round" 
                style={props.style}
            >
                <polygon points="12 2 15.09 8.26 22 9.27 17 14.14 18.18 21.02 12 17.77 5.82 21.02 7 14.14 2 9.27 8.91 8.26 12 2"></polygon>
            </svg>
        </label>
    );
}

export default Star;
src\style.css
* {
  margin: 0;
  padding: 0;
  box-sizing: border-box;
}

.container {
  padding: 16px;
  margin: 16px auto;
}

.result {
  text-align: center;
  margin-bottom: 16px;
  font-family: 'Segoe UI', Tahoma, Geneva, Verdana, sans-serif;
}

.stars {
  display: flex;
  justify-content: center;
  gap: 8px;
}

.star {
  position: relative;
  cursor: pointer;
}

.stars_radio-input {
  position: absolute;
  top: 0;
  left: 0;
  width: 1px;
  height: 1px;
  clip: rect(1px, 1px, 1px, 1px);
}