サイトトップ

Director Flash 書籍 業務内容 プロフィール

HTML5テクニカルノート

Create React App + React DnD 03: アプリケーションを組み立て直す


React DnDサイトの「Tutorial」には、でき上がりの作例がCodeSandboxに公開されています(サンプル001)。ところが、見たことのないモジュールが並んでいたり、コードもよく見ると少しずつ違っているようです。そこで、今回と次回の2回にわたり、前回のサンプル001を公式作例に沿うように書き替えてみます。ただし、コードの細かなところは手直ししました。

サンプル001■Chessboard Tutorial

01 コンポーネントを名前つきでexportする

まず、コンポーネントのexportに、基本的にdefaultは用いられず、名前をつけていることです。React DnDの開発に当たっても、そのような方針がとられています(GitHub「Releases」の「v11.0.0」参照)。

exportするコンポーネントは変数(const)で名前づけし、export defaultは外してください。そして、importするコンポーネントは、オブジェクトの分割代入で、名前を定めて取り出します。

src/components/Board.js

// function Board({ knightPosition }) {
export const Board = ({ knightPosition }) => {

};

// export default Board;

src/index.js

// import Board from './components/Board';
import { Board } from './components/Board';

ほぼすべてのコンポーネントのexportに名前づけし、importには名前を正しく定めなければなりません。地道な作業にはなるものの、とくにむずかしいことはないでしょう。

src/components/BoardSquare.js

// const BoardSquare = ({ x, y, children }) => {
export const BoardSquare = ({ x, y, children }) => {

};

// export default BoardSquare;

src/components/Knight.js

// const Knight = () => {
export const Knight = () => {

};

// export default Knight;

src/components/Board.js

// import BoardSquare from './BoardSquare';
import { BoardSquare } from './BoardSquare';
// import Knight from './Knight';
import { Knight } from './Knight';

src/components/Square.js

// const Square = ({ black, children }) => {
export const Square = ({ black, children }) => {

}

// export default Square;

src/components/Overlay.js

// const Overlay = ({ color }) => {
export const Overlay = ({ color }) => {

};

// export default Overlay;

src/components/BoardSquare.js

// import Square from './Square';
import { Square } from './Square';
// import Overlay from './Overlay';
import { Overlay } from './Overlay';

02 盤面のコンポーネントから駒の表示を切り分ける

つぎに、盤面のモジュールsrc/components/Board.jsから、駒を表示する要素は新たなコンポーネント(Piece)に切り分けます。新しいモジュールsrc/components/Piece.jsは、以下のコード001のとおり数行です。とはいえ、盤面のコンポーネント(Board)のコードが少し混み合っているので、分けられるものは分けた方がすっきりするでしょう。

src/components/Board.js

// import { Knight } from './Knight';
import { Piece } from './Piece';

function renderSquare(i, [knightX, knightY]) {

	return (
		<div

		>
			<BoardSquare x={x} y={y}>
				 {/* {renderPiece(x, y, [knightX, knightY])} */}
				<Piece isKnight={knightX === x && knightY === y} />
			</BoardSquare>
		</div>
	);
}
/* function renderPiece(x, y, [knightX, knightY]) {
	const isKnightHere = knightX === x && knightY === y;
	return isKnightHere ? <Knight /> : null;
} */

コード001■駒を表示するモジュール

src/components/Piece.js

import { Knight } from './Knight';

export const Piece = ({ isKnight }) => 
	isKnight ? <Knight /> : null;

03 盤面のマス目要素をArray.from()メソッドでつくる

今回の締めは、公式作例にはない書き替えです。モジュールsrc/components/Board.jsでは、盤面に並べる64マスの要素を、for文のループで書いていました。これでも、とくに問題はありません。けれど、配列(Array)には引数にコールバック関数を渡す新しい構文のメソッドが備わりました。これらを用いた方が、応用しやすく、有利なことが少なくありません。

今回使うのは、Array.from()メソッドです。つぎのコードに書き改めれば、配列の長さ64の未定義(undefined)要素それぞれを、マス目のJSX要素で置き替えた新たな配列(squares)がつくられます。メソッドの構文について詳しくは、「ECMAScript 6のArrayに関わる構文を試す」の「Array.from()メソッド」をお読みください。

src/components/Board.js

export const Board = ({ knightPosition }) => {
	/* const squares = [];
	for (let i = 0; i < 64; i++) {
		squares.push(renderSquare(i, knightPosition));
	} */
	const squares = Array.from(new Array(64), (_, i) => renderSquare(i, knightPosition));

};

書き替えの済んだ盤面のモジュールsrc/components/Board.jsの記述全体が、つぎにまとめたコード002です。前述01「コンポーネントを名前つきでexportする」で加えた修正については、それぞれ数行ずつですし、同じパターンですので、モジュールのコード全体を掲げることは省きます。以下にサンプル002として公開したCodeSandbox作例をご覧ください。

コード002■盤面のモジュール

src/components/Board.js

import { DndProvider } from 'react-dnd';
import { HTML5Backend } from 'react-dnd-html5-backend'
import { BoardSquare } from './BoardSquare';
import { Piece } from './Piece';

const boardStyle = {
	width: 500,
	height: 500,
	border: '1px solid gray',
	display: 'flex',
	flexWrap: 'wrap'
};
const squareStyle = { width: '12.5%', height: '12.5%'};
function renderSquare(i, [knightX, knightY]) {
	const x = i % 8;
	const y = Math.floor(i / 8);
	return (
		<div
			key={i}
			style={squareStyle}
		>
			<BoardSquare x={x} y={y}>
				<Piece isKnight={knightX === x && knightY === y} />
			</BoardSquare>
		</div>
	);
}
export const Board = ({ knightPosition }) => {
	const squares = Array.from(new Array(64), (_, i) => renderSquare(i, knightPosition));
	return (
		<DndProvider backend={HTML5Backend}>
			<div style={boardStyle}>
				{squares}
			</div>
		</DndProvider>
	);
};

サンプル002■React DnD 03: Chess board and lonely Knight

Create React App + React DnD


作成者: 野中文雄
作成日: 2021年05月01日


Copyright © 2001-2020 Fumio Nonaka.  All rights reserved.