Trouble with read ROOT file in React

Dear all,

I’m currently struggling to create a webpage that can handle ROOT files. Utilizing JSROOT, I managed to successfully read ROOT files and draw histograms on my webpage, thanks to the documentation available at JavaScript ROOT API examples . Below is the code snippet I used, which closely resembles the reference:

<!DOCTYPE html>
<html lang="en">
   <head>
      <meta charset="utf-8">
      <title>Reading object from the ROOT file</title>
   </head>
   <body>
       <h1>Hi</h1>
      <div id="drawing" style="width:800px; height:600px"></div>
   </body>
   <script type='module'>
       import { openFile, draw } from './modules/main.mjs';
       let file = await openFile('./histo_dt_4000.root');
       let obj = await file.readObject('h2;1');
       draw('drawing', obj, 'colz');
   </script>

</html>

The rendered output appears as shown in the image below:

Now, my objective is to achieve the same functionality within a React environment since I’ve already designed my webpage using React. I attempted to adapt the aforementioned process to React, but I encountered some discrepancies in the syntax between JavaScript and JSX. Here’s where I currently stand:

import { openFile, draw } from '../node_modules/jsroot/modules/main.mjs';
import React, { useState, useEffect } from 'react';

function App() {

    async function fetchData() {
        try {
          let file = await openFile("./histo_dt_4000.root");
          let obj = await file.readObject('h2;1');
          draw('drawing', obj, 'colz');
        } catch (error) {
          console.error('Error fetching data:', error);
        }
    }

    useEffect(() => {
      fetchData();
      // Cleanup function (optional)
      return () => {
        // Cleanup logic (if needed)
      };
    }, []);

  return ( /*other codes display the webpage*/
  );
}

export default App;

However, I encountered an error stating: “Error: Not a ROOT file ./histo_dt_4000.root.” Despite verifying the correctness of my file path multiple times and confirming that my ROOT file is functional, the error persists. I’ve attached my ROOT file containing two histograms for reference:
histo_dt_4000.root (49.9 KB)

I’ve exhaustively searched for solutions to my JSROOT-related issues by referring to other documentation, but finding resources specifically addressing JSROOT in React has proven to be challenging. Therefore, I’ve decided to seek assistance here. Any insights or guidance would be greatly appreciated.

Thank you in advance!

ROOT Version: 6.30.02
Platform: macOS Sonoma 14.2.1
Compiler: iTerm?


Hi,

I add @linev in the loop, the expert of JS graphics.

Best,
Danilo

1 Like

Hi,

First of all - are you sure that path "./histo_dt_4000.root" to your file correct?
Try to open browser console and check status of http requests to your file.
It should looks like:

Regards,
Sergey

1 Like

Thank you all. The following is my directory structure. Since App.js and my root file (histo_dt_4000.root) are in the same directory, I believe the path is correct.


When I check the status of HTTP requests, it seems that the file I’m trying to load does not exist.

Even though I imported ‘openFile’ and ‘draw’ from jsroot/modules/main.mjs, I cannot see the screen as you shared. Is there something that I’m missing?

// App.js
/* eslint-disable */

import React, { useState, useEffect } from 'react';
import './App.css';
import { openFile, draw } from '../node_modules/jsroot/modules/main.mjs';

Thanks!

Here is my app.js:

/* eslint-disable */

import React, { useState, useEffect } from 'react';
import './App.css';
import { openFile, draw } from '../node_modules/jsroot/modules/main.mjs';

function App() {
    
    let [title, title_ch] = useState(['blah1', 'blah2', 'blah3']);
    let mainfont = { color : 'white', fontSize : '30px' };
    let [compo, compo_ch] = useState(false);
    let [detail1, setdetail1] = useState('detail');
    
    let [like_num, like_num_ch] = useState(0);

    async function fetchData() {
        try {
          let file = await openFile("./histo_dt_4000.root");
          let obj = await file.readObject('h2;1');
          draw('drawing', obj, 'colz');
        } catch (error) {
          console.error('Error fetching data:', error);
        }
    }
    
    useEffect(() => {
      fetchData();
      // Cleanup function (optional)
      return () => {
        // Cleanup logic (if needed)
      };
    }, []);

    function section_ch(){
        var newArr = [...title];
        newArr[0] = 'blah_extra';
        title_ch( newArr );
    }
    
    function section_pre(){
        var newArr2 = [...title];
        newArr2[0] = 'blah1';
        title_ch( newArr2 );
    }

  return (
    <div className="App">
        <div className="black-nav">
          <div style={ mainfont }><a href="index.html" className="homepage">qwerty</a></div>
        </div>
          
          <nav>
              <h2>Welcome!</h2>
              <h3>Contents</h3>
              <ul>
                  <li>
                      <a href="index.html"><p>Basic Calculator</p></a>
          
                      <a href="index.html"><p>Matrix Mutlplier</p></a>
                </li>
            </ul>
        </nav>
        
        <div className="mainbody">
          <button onClick={ section_pre }>Previous</button>
          <button onClick={ section_ch }>Next</button>
        <div className="list">
          <h3>My first react proejct</h3>
          <p>Feb 7, 2024</p>
          <hr/>
        </div>
        
        <div className="list">
          <h3> { title[0] } <span onClick={ ()=>{ like_num_ch(like_num + 1) } }>🧡</span> { like_num } </h3>
          <p>Feb 7, 2024</p>
          <hr/>
        </div>
          
        <div className="list">
          <h3>{ title[1] } <span onClick= { ()=> { compo_ch(!compo)}}> { compo ? "hold up" : "details" }</span>

              </h3>
          <p>Feb 7, 2024</p>
          <hr/>

        </div>
          {compo && <Modal onClose={()=>compo_ch(false)} />}
          </div>
    </div>
  );
}

function Modal({ onClose }){
    return (
            <div className="modal">
              <h2>Title</h2>
              <p>Date : </p>
              <p>Details : </p>
            <button onClick={ onClose }>Hold up</button>
            </div>
            );
}

export default App;

My screen may look different as yours. I am using Firefox browser, your browser most probably Safari.

Please try to find in network logs request to “histo_dt_4000.root” file and check that are return codes from the server. Either it is 404 (file is missing) or may be some other problem. I just want to see which kind of errors are reported in network logs.

You also can try to see browser console for any suspicious messages there.

This shows the error message.

Please check network console once again. It should include requests to “histo_dt_4000.root” file.

If you cannot find - can you provide me a code that I can test myself.

As I added the histo_dt_4000.root file into the public directory, then I can see the response. I attached the screenshot of it. Is this the correct action you were referring to? In my view, it seems that the file was read successfully, but the error message still says Not a ROOT file ./histo_dt_4000.root.

I’m not sure that I’m providing the correct response, so I attached the file.

Or
myweb.zip (287.7 KB)
which is not including node_modules directory. (By running create-react-app, react automatically generated this directory.)

Hi,

I can see that content range of your file is 0-1023/1950.
It does not look like valid size of ROOT file - it must be at least 5K.

Maybe server does not like extra url “stamp” parameter which is submitted with http query.
This is special JSROOT feature to avoid nasty browser caching when reading same file many times.
But one can disable this feature. Just add following code:

import { openFile, draw, settings } from '../node_modules/jsroot/modules/main.mjs';

settings.UseStamp = false;

Maybe this helps.

Regards,
Sergey

2 Likes

Oh, Now it works!!! Thank you !!!

1 Like