Integrating threejs dynamically into a Create React App environment

When I am dynamically loading Three.js, the variable THREE is not found. I have created a React project using create-react-app and copied the three js file into the public folder. Here's the directory structure:

src
public
├── js
│   └── threejs
│       ├── Detector.js
│       ├── OrbitControls.js
│       ├── postprocessing
│       │   ├── BloomPass.js
│       │   ├── ShaderPass.js
│       │   └── ...
│       ├── shaders
│       │   ├── BasicShader.js
│       │   ├── BleachBypassShader.js
│       │   ├── ....
│       ├── three.js
│       └── three.min.js

I have created a class that loads three.js as well as any files that are part of the examples/js folder dynamically. It also triggers the onLoaded callback when done:

// Dependencies
import React from 'react';

export default class DynamicThreeJsLoader extends React.Component {

    constructor(props) {
        super(props);   
        this.unloaded = [
            '/js/threejs/three.js',
            '/js/threejs/OrbitControls.js'
        ];
        this.loaded = [];
    }

    loadScript(address) {
        let script = document.createElement('script');
        script.setAttribute('type', 'text/javascript');  // optional
        script.setAttribute('src', address);
        script.onload = () => {
            this.loaded.push(address);
            this.checkLoaded();
        };
        document.getElementsByTagName('head')[0].appendChild(script);
    }

    checkLoaded() {
        if(this.loaded.length >= this.unloaded.length) {
            if(this.props.onLoaded) {
                this.props.onLoaded();
            }
        }
    }

    componentDidMount() {
        while(true) {
            let script = this.unloaded.shift();
            let script_path = `${process.env.PUBLIC_URL}${script}`;
            if(script) {
                this.loadScript(script_path);
            }
            else {
                break;
            }
        }
    }

    render() {
        return null;
    }
}

This is how the script is used:

import React from 'react';
import DynamicThreeJsLoader from './dynamic_threejs_loader';

export default class PageBackground extends React.Component {

    constructor(props) {
        super(props);
        this.backgroundRef = React.createRef();
    }

    loadScene() {
        let scene = new THREE.Scene();
        scene.background = new THREE.Color( 0xcccccc );

        let renderer = new THREE.WebGLRenderer( { antialias: true } );
        renderer.setPixelRatio( window.devicePixelRatio );
        renderer.setSize( window.innerWidth, window.innerHeight );
        this.backgroundRef.current.appendChild( renderer.domElement );

        let camera = new THREE.PerspectiveCamera( 60, window.innerWidth / window.innerHeight, 1, 1000 );
        camera.position.set( 400, 200, 0 );

        // controls
        let controls = new THREE.OrbitControls( camera, renderer.domElement );
    }

    render() {
        return (
            <div>
                <DynamicThreeJsLoader onLoaded={ () => this.loadScene() } />
                <div ref={this.backgroundRef} ></div>
            </div>
        );
    }
}

I have tested the code and it successfully loads the scripts. However, I encounter the following error:

./src/page_background.jsx
  Line 36:  'THREE' is not defined  no-undef
  Line 37:  'THREE' is not defined  no-undef

Answer №1

Regrettably, I was compelled to uninstall and deactivate EsLint, along with disabling the functionality which prohibited sourcing content from external origins. While there are concerns about its potential risks, implementing appropriate file system permissions may help mitigate those dangers.

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

What is the best way to retrieve an ID when parsing JSON recursively?

Could you provide guidance on how to retrieve the IDs of all children when parsing JSON data? I have attempted to use a recursive function, but it seems to be calling infinitely. For reference, here is my code snippet: http://jsfiddle.net/Ds8vQ/ for(var ...

Tips for limiting the frequency of Angular provider loading instances

I have created a provider (I tried with a controller as well, but got the same results). Here is my code: .provider('socketio', function() { this.socket = io.connect("//localhost); console.log("LISTENING..."); this.$get = function() ...

Encountering an issue while updating information following the migration to vue-chartjs 4

I recently upgraded from vue-chartjs version 3 to version 4. I successfully migrated my LineChart component by updating the template section and removing the draw method calls. This component is utilized for two separate charts. However, when I close the ...

There is nothing like Python Bottle when it comes to parsing JSON data from

In my React code, I have the following: const payload = { x : x, y : y } fetch("http://localhost:8080/update_game", { method: "POST", body: JSON.stringify(payload)}) And in Python, I have this implementation: @post(&ap ...

How to determine the length of a JavaScript object

Would like help determining the length of the report_data(object) key using the provided code, but it seems to result in a value of 3. a={report_freq: "daily", report_item_num: 2, report_num: 39, report_data: "{}"} Object {report_freq: "daily", report_ite ...

Tips for cutting down on bundle size in your WEBPACK setup when using VUEJS

I have tried numerous tutorials to reduce the size of my bundle, but none of them seem to be affecting the bundle size and I can't figure out why. Every time I integrate new code into webpack, the bundle size remains unchanged. (The application is c ...

Removing the loading spinner from Ag Grid

While utilizing ag-grid with rowModelType=serverSide, I have encountered an issue where the loading overlay includes a spinner as shown in the image below. My goal is to eliminate this spinner from the overlay. I attempted using hideOverlay(), but it seems ...

Error encountered in my application due to Node.js (Error [ERR_HTTP_HEADERS_SENT]: Unable to change headers once they have been sent to the client)

Experiencing an error message in my application when typing nodeJS. Please assist. , Encountering an error after sending the first POST request while running the app. const express = require('express') const Workout = require("../models/work ...

Show User-Specific Information Using DataTable

After conducting extensive research, I have been unable to find a suitable example to reference. My goal is to customize my DataTable so that it only displays data relevant to the currently logged-in user (admin accounts will have access to all data). I am ...

Tips for managing mouse over events in legends on highcharts

I have successfully implemented mouseover/mouseout event handling for donut slices. Please review my code below: http://jsfiddle.net/nyhmdtb8/6/ Currently, when I hover over a slice, it highlights that slice and greys out all others. Is it possible to ac ...

Move a <div> using a handle (without using JQuery)

I devised a plan to create a moveable div with a handle and came up with this code snippet: var mydragg = function() { return { move: function(divid, xpos, ypos) { divid.style.left = xpos + 'px'; divid.style.top = ypos + &apo ...

How to navigate using Material UI Drawer selections?

I am currently working with the Material UI React drawer and I'm facing some confusion in implementing selection to trigger a change in a component. For instance, when selecting "Get Videos", it should call the component that makes an AXIOS call to S3 ...

What is the best way to import a YAML file into a Vue project?

As a newcomer to Vue and the world of web development, I recently embarked on building a small app. In order to store data with comments, I opted to use YAML instead of JSON. I experimented with two different YAML parsers: https://github.com/nodeca/js-ya ...

Transfer the cropped image to the database through AJAX on the client side and PHP on the server side

I am attempting to upload an image to a Database using JavaScript on the client-side and PHP on the server-side. The first step is selecting an image from the gallery. After zooming and cropping the image, it should be passed to the database. The issue ...

How can I create multiple divs that look alike?

I've taken on the challenge of developing our own interpretation of Conway's "Game of Life" for a project. To represent my 20x20 grid, I decided to create nested divs - the whole grid is one div, each row is a div, and every cell within that is a ...

In Node.js, the `res.send()` function is called before the actual functionality code is executed

As a newcomer to node js, I am currently working on an app where I query the MySql DB and process the results using node js. One issue I have encountered is that if my initial query returns null data, I then need to perform another query and further proc ...

Create a drag-and-drop interface and link elements together using a custom JavaScript library

Seeking a solution or Javascript library to create a scientific modeling application, similar to flowchart software such as Visio. The ability to add elements and connect them by clicking and dragging is essential. https://i.stack.imgur.com/vSZpB.png The ...

What is the recommended data type for Material UI Icons when being passed as props?

What specific type should I use when passing Material UI Icons as props to a component? import {OverridableComponent} from "@mui/material/OverridableComponent"; import {SvgIconTypeMap} from "@mui/material"; interface IconButtonProps { ...

How to make a straightforward task list using ExpressJS

As a beginner, I am attempting to create a basic todo list using ExpressJS. Currently, my goal is to simply display some hardcoded todos that I have in my application. However, I seem to be struggling to identify the mistake in my code. Any assistance woul ...

A Comprehensive Guide: Obtaining the Final Tab from a JSON using API

What is the method to extract the last tab from a given JSON code? { "claimed_levels": { "level_1", "level_2" } } I want to display the level when someone types "!levels". The desired output format should be: Your current level is "2" ...