Reactサンプルアプリ開発 プラニングポーカー (3) 親コンポーネントへ反映

Poker サンプル開発

ポップアップでモーダル表示したデッキで選択されたカードを親コンポーネントへ反映させる。

モーダルダイアログに包含されるDeckコンポーネントの<div>タグにonClick属性を指定する(9行目)。このとき、カードに書かれたポイントを渡したいのでハンドラメソッドを直接指定するのではなく、アロー関数で記述するのがポイント。

export const Deck: FunctionComponent<DeckProps> = (props) => {

  const handleCardSelect = (point: string) => {
    props.onCardSelected(point);
  }

  const cards = props.points.map((point) => {
    return (
      <div className="deck-card" onClick={() => handleCardSelect(point)} >
        <span className="point">{point}</span>
      </div>
    );
  });
  return (
    <div className="deck">
      {cards}
    </div>
  );
}

親コンポーネントへ伝搬は、propsを経由する(4行目)。
propsの定義は以下のようになっている。

type DeckProps = {
  points: string[];
  onCardSelected: (point: string) => void;
}

親のPlayerコンポーネントはreact-modalModalコンポーネントの子にDeckコンポーネントを配置しているので、属性onCardSelectedに自身のハンドラメソッドを指定する(3行目)。

      <Modal isOpen={modalIsOpen} onRequestClose={handleModalClose}
        contentLabel="test" style={customStyles} >
        <Deck points={points} onCardSelected={handleCardSelect} />
      </Modal

handleCardSelectメソッドでは、ステート変数を更新する(選ばれたカードのポイントでビッドを更新するのと、モーダルを閉じるための状態の更新)。

  const handleCardSelect = (point: string) => {
    setBid(point);
    setModalIsOpen(false);
  }

ステート変数の更新関数はuseStateで定義済み。

export const Player: FunctionComponent<PlayerProps> = (props) => {
  const [modalIsOpen, setModalIsOpen] = useState(false);
  const [bid, setBid] = useState(props.bid)

これで、デッキのカードを選択するとダイアログが閉じ、プレイヤーのカードが更新されるようになった。

今回のソース:

import React, { FunctionComponent, useState } from "react";
import Modal from 'react-modal';
import { Deck } from "./Deck";

Modal.setAppElement('#app');
const customStyles = {
  overlay: {
    backgroundColor: "rgba(0, 0, 0, 0.7)"
  },
  content: {
    top: '50%',
    left: '50%',
    right: 'auto',
    bottom: 'auto',
    marginRight: '-50%',
    padding: 0,
    transform: 'translate(-50%, -50%)'
  }
};

export type PlayerProps = {
  name: string;
  icon: number;
  bid: string;
  open: boolean;
}

export const Player: FunctionComponent<PlayerProps> = (props) => {
  const [modalIsOpen, setModalIsOpen] = useState(false);
  const [bid, setBid] = useState(props.bid);
  const points = ["0", "1", "2", "3", "5", "8"];

  const handleModalOpen = () => {
    setModalIsOpen(true);
  }

  const handleModalClose = () => {
    setModalIsOpen(false);
  }

  const handleCardSelect = (point: string) => {
    setBid(point);
    setModalIsOpen(false);
  }

  return (
    <div className="player">
      <div className="player-info">
        <div className={"player-icon-" + props.icon}>
        </div>
        <div className="player-name">{props.name}</div>
      </div>
      <div className="player-card" onClick={handleModalOpen}>
        <span className="point">{bid}</span>
      </div>
      <Modal isOpen={modalIsOpen} onRequestClose={handleModalClose}
        contentLabel="test" style={customStyles} >
        <Deck points={points} onCardSelected={handleCardSelect} />
      </Modal>
    </div>
  )
}
import React, { FunctionComponent, useState } from "react";

type DeckProps = {
  points: string[];
  onCardSelected: (point: string) => void;
}

export const Deck: FunctionComponent<DeckProps> = (props) => {

  const handleCardSelect = (point: string) => {
    props.onCardSelected(point);
  }

  const cards = props.points.map((point) => {
    return (
      <div className="deck-card" onClick={() => handleCardSelect(point)} >
        <span className="point">{point}</span>
      </div>
    );
  });
  return (
    <div className="deck">
      {cards}
    </div>
  );
}

コメント

  1. […] プラニングポーカー (2) モーダルダイアログReactサンプルアプリ開発 プラニングポーカー (3) 親コンポーネントへ反映Reactサンプルアプリ開発 プラニングポーカー (4) […]

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