skip to Main Content

I am a junior Frontend Developer. I need help for this issue.

I am trying to use JSXGraph with React+Vite. When I put the example codes on my React component, the height of SVG goes infinitive. Here is the code :

import { JSXGraph } from "jsxgraph";

function JSXBoard () { 
    const BOARDID = 'board-0';
 
    // input data from LMS
    
    let input = [
        2, 4,   // point A(x, y)
        12, 6,  // point B(x, y)
        8, 12,  // point C(x, y)
        2       // unit
    ];
    
    // JSXGraph board
    
    const board = JXG.JSXGraph.initBoard(BOARDID, {
        boundingbox: [0, 15, 15, 0],
        axis: true,
    showCopyright:true,
    showNavigation:true,
    });

    let A = board.create('point', [input[0], input[1]], {
        name: '\(A\)',
        snapToGrid: true,
        label: {offset: [-25, -10], fontSize: 16}
    });
    let B = board.create('point', [input[2], input[3]], {
        name: '\(B\)',
        snapToGrid: true,
        label: {offset: [10, -5], fontSize: 16}
    });
    let C = board.create('point', [input[4], input[5]], {
        name: '\(C\)',
        snapToGrid: true,
        label: {offset: [0, 15], fontSize: 16}
    });
    let ABC = board.create('polygon', [A, B, C], {
        borders: {strokeWidth: 2}
    });
    
    return (  
        <>
        </>
    )
}

export default JSXBoard;

and HTML code is :

<div id="board-0-wrapper" className="jxgbox-wrapper">
 <div id="board-0" className="jxgbox" data-ar="1 / 1"></div>
</div>

and plese find the codes at https://github.com/ozdilkazim/React-Structural-Engineering-Project
and the deployed version of infinite height : https://structuralengineering.netlify.app/

I have tried to convert the code to an other component and still have same issue

2

Answers


  1. In the HTML it is not className, it’s class. className is a React thing and is for actual JSX in the component return, and you currently have none (<></>).

    That means the styles aren’t being applied and those include a height property on the container which will prevent this behaviour. However, that HTML shouldn’t exist outside the component anyway, so let’s shelve that for now and look at the overall approach.

    It is strange for a React component to reach out into DOM that exists outside of the React component itself. You really want to render that wrapping HTML in the React component and then load this "JsxGraph" library into it.

    That can be done by using a ref that stores the HTML element reference for the board-0 element and passing this to initBoard. We also need to wrap the initialisation in an effect so that this runs only once on mount and not on every render. We also return a cleanup function from the effect that unbinds the library if/when when the parent component is unmounted.

    You can also delete any HTML snippet you added after this.

    import React, { useRef, useEffect } from 'react'
    import { JSXGraph } from "jsxgraph";
    
    function JSXBoard() {
      const boardRef = useRef();
    
      useEffect(() => {
        // input data from LMS
    
        let input = [
          2,
          4, // point A(x, y)
          12,
          6, // point B(x, y)
          8,
          12, // point C(x, y)
          2, // unit
        ];
    
        // JSXGraph board
    
        const board = JXG.JSXGraph.initBoard(boardRef.current, {
          boundingbox: [0, 15, 15, 0],
          axis: true,
          showCopyright: true,
          showNavigation: true,
        });
    
        let A = board.create("point", [input[0], input[1]], {
          name: "\(A\)",
          snapToGrid: true,
          label: { offset: [-25, -10], fontSize: 16 },
        });
        let B = board.create("point", [input[2], input[3]], {
          name: "\(B\)",
          snapToGrid: true,
          label: { offset: [10, -5], fontSize: 16 },
        });
        let C = board.create("point", [input[4], input[5]], {
          name: "\(C\)",
          snapToGrid: true,
          label: { offset: [0, 15], fontSize: 16 },
        });
        let ABC = board.create("polygon", [A, B, C], {
          borders: { strokeWidth: 2 },
        });
        
        return () => {
          JXG.JSXGraph.freeBoard(boardRef.current)
        }
      }, []);
    
      return (
        <div id="board-0-wrapper" className="jxgbox-wrapper">
          <div ref={boardRef} id="board-0" className="jxgbox" data-ar="1 / 1"></div>
        </div>
      );
    }
    
    export default JSXBoard;
    
    

    It’s worth noting many graphing libs exist that are built for React. JsxGraph is not hence binding it to work inside a React component means you have to write the glue code like above. I don’t know if it’s an option for you but things like visx and chart.js exist, to name only a couple of many.

    Login or Signup to reply.
  2. This is a problem which is independent from react and has been noted by a few developers before:

    A look at the source code shows that there is no height or max-height property set for the JSXGraph div which generates an infinite loop. Responsible for the infinite loop seems to be the combination of the CSS property box-sizing:box-content and the JSXGraph board attribute resize:{enabled: true} (the default) value. resize adapts to JSXGraph to a change of the div size and so does box-sizing. The solution is either to set height or max-height of the div or to disable resizing of JSXGraph by resize:{enabled: false}.

    Regarding JSXGraph with react: there are two projects on github about this: https://github.com/sytabaresa/jsxgraph-react-js (seems to be abandoned) and https://gist.github.com/stemcstudio/3ea4e381d4595d2e022a4db2b7b20f66. An "official" wrapper would be very welcome but we, the JSXGraph, can not do that. Help from the community would be very welcome here.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search