reactjstypescriptchessboard.js

How to use Chessboard.js with Reactjs?


I've been looking a bit at chessboardjs (https://chessboardjs.com/) as a way to get some practice with some React coding. However, I haven't been able to get the simple example of just showing the board in my app working. the documentation says to use <div id="board" style={{width: 400}}/> in the HTML, and var board = ChessBoard('board', 'start'); to get startet. However, ChessBoard('board', 'start'); gives me an "object not a function" compilation error. I've tried fiddling a lot of different things (such as adding the anonymous function with the jquery tag), but I seem to be doing something wrong. I hope someone can spot it.

My React app (using typescript) has the standard App component, which just has a ChessComponent, which looks the following way:

import * as React from 'react';
import {ChessBoard} from 'chessboardjs';
import * as $ from 'jquery';

class ChessComponent extends React.Component {
    constructor(props:any) {
        super(props);
    }

    componentDidMount() {
        $(function() {
            var board = ChessBoard('board', 'start');
        });
    }

    render() {
        return (
            <div id="board" style={{width: 400}}/>
        )
    }
}

export default ChessComponent

and my package.json looks like this:

  {
    "name": "chess-app",
    "version": "0.1.0",
    "private": true,
    "dependencies": {
      "chess": "^0.4.1",
      "chessboardjs": "0.0.1",
      "jquery": "^3.4.0",
      "react": "^16.5.2",
      "react-bootstrap": "^0.32.4",
      "react-dom": "^16.5.2",
      "react-scripts-ts": "3.1.0",
      "tslint": "^5.11.0",
      "tslint-react": "^3.6.0"
    },
    "scripts": {
      "start": "react-scripts-ts start --noUnusedParameters=false",
      "build": "react-scripts-ts build",
      "test": "react-scripts-ts test --env=jsdom",
      "eject": "react-scripts-ts eject"
    },
    "devDependencies": {
      "@types/chessboardjs": "^0.3.1",
      "@types/jest": "^23.3.2",
      "@types/jquery": "^3.3.29",
      "@types/node": "^10.11.3",
      "@types/react": "^16.4.14",
      "@types/react-dom": "^16.0.8",
      "typescript": "^3.1.1"
    }
   }

Solution

  • Just in case anyone else out there is struggling with a similar issue, I thought I would come back to this and answer my own question.

    One trick is to add the necessary scripts to index.html:

    <script src="https://code.jquery.com/jquery-2.1.4.js"></script>
    <script src="https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.js"
            integrity="sha384-8Vi8VHwn3vjQ9eUHUxex3JSN/NFqUg3QbPyX8kWyb93+8AC/pPWTzj+nHtbC5bxD"
            crossorigin="anonymous"></script>
    <link rel="stylesheet"
          href="https://unpkg.com/@chrisoakman/chessboardjs@1.0.0/dist/chessboard-1.0.0.min.css"
          integrity="sha384-q94+BZtLrkL1/ohfjR8c6L+A6qzNH9R2hBLwyoAfu3i/WCvQjzL2RQJ3uNHDISdU"
          crossorigin="anonymous">
    

    That way, both jquery and the chessboardjs functionality are available on the window object. now you can call window.Chessboard to make the board (with a bit of setup).

    A quick-n-dirty setup of chessboardjs using reactjs-typescript could look like this:

    import React from 'react';
    import './App.css';
    
    // This is a bit of a hack to declare jquery on the window object. It also makes it possible to call window.chessBoard further below
    declare var window : any; 
    window.$ = window.jQuery = $;
    
    export default class App extends React.Component {
      
      // Please disregard the massive overuse of the any type here
      private boardRef: any;
      private chessBoard: any;
      private boardId: string;
      private defaultConfig: any;
    
      constructor(props: any) {
        super(props);
        this.boardRef = React.createRef();
        this.boardId = "board1";
        const themePath = process.env.PUBLIC_URL + '/assets/img/chesspieces/wikipedia/{piece}.png'
    
        this.defaultConfig = {
          appearSpeed: 25,
          draggable: true,
          dropOffBoard: 'snapback',
          moveSpeed: 25,
          orientation: 'white',
          position: 'start',
          showErrors: 'console',
          showNotation: true,
          snapSpeed: 25,
          snapbackSpeed: 50,
          pieceTheme: themePath,
          sparePieces: false,
          trashSpeed: 25,
        };
      }
    
    
      componentDidMount() {
        if (window && !window.ChessBoard) return
        if (window && !window.$) return
    
        this.chessBoard = window.ChessBoard(this.boardId, this.defaultConfig);
      }
      
      componentWillUnmount() {
        this.chessBoard.destroy();
      }
      
      render() {
        return (
          <div className="App">
            <div id={this.boardId} style={{width: "400px"}} ref={this.boardRef}></div>
          </div>
          ); 
        } 
      }
    

    However, if you are looking at using Chessboard.js with React I suggest having a look at Simon Ansells React-ChessboardJs-Wrapper: https://github.com/ginger-gm/react-chessboardjs-wrapper

    This also makes it easy to add promotion-dialogues to your board.

    If you are sitting in a similar pickle with integrating React with other libraries, I also recommend reading their doc on the subject, which I somehow originally missed: