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

モーダルダイアログに包含される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-modal
のModal
コンポーネントの子に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>
);
}
コメント
[…] プラニングポーカー (2) モーダルダイアログReactサンプルアプリ開発 プラニングポーカー (3) 親コンポーネントへ反映Reactサンプルアプリ開発 プラニングポーカー (4) […]