HTML5テクニカルノート
Create React App + React DnD 03: アプリケーションを組み立て直す
- ID: FN2105001
- Technique: ECMAScript 2015
- Library: React 17.0.2 / React DnD 14.0.2
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.jssrc/index.js// function Board({ knightPosition }) { export const Board = ({ knightPosition }) => { }; // export default Board;
// import Board from './components/Board'; import { Board } from './components/Board';
ほぼすべてのコンポーネントのexport
に名前づけし、import
には名前を正しく定めなければなりません。地道な作業にはなるものの、とくにむずかしいことはないでしょう。
src/components/BoardSquare.jssrc/components/Knight.js// const BoardSquare = ({ x, y, children }) => { export const BoardSquare = ({ x, y, children }) => { }; // export default BoardSquare;
src/components/Board.js// const Knight = () => { export const Knight = () => { }; // export default Knight;
// import BoardSquare from './BoardSquare'; import { BoardSquare } from './BoardSquare'; // import Knight from './Knight'; import { Knight } from './Knight';
src/components/Square.jssrc/components/Overlay.js// const Square = ({ black, children }) => { export const Square = ({ black, children }) => { } // export default Square;
src/components/BoardSquare.js// const Overlay = ({ color }) => { export const Overlay = ({ color }) => { }; // export default Overlay;
// 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.jsexport 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
- Create React App + React DnD 01: ドラッグ&ドロップの前に ー クリックで動かす
- Create React App + React DnD 02: ドラッグ&ドロップで動かす
- Create React App + React DnD 03: アプリケーションを組み立て直す
- Create React App + React DnD 04: アプリケーションの処理を改善する
作成者: 野中文雄
作成日: 2021年05月01日
Copyright © 2001-2020 Fumio Nonaka. All rights reserved.