Как интегрировать простой (ванильный) JavaScript в ReactJS?

Oct 01 2020

Я пытаюсь использовать эту 3D-визуализацию gio в своем приложении ReactJs. Код написан на ванильном JavaScript. Я также нашел оболочку для React и попробовал ее, но я не могу выбрать выбранную страну ( onCountryPicked()), как показано в их демонстрации . Это основная причина, по которой я предпочитаю ванильную реализацию JavaScript вместо оболочки. Однако мне сложно интегрировать ванильную реализацию JavaScript с моим приложением ReactJs.

Я посмотрел вокруг, чтобы решить проблему, но ресурсы, которые я нашел, мне не помогли. Ниже приведены некоторые из мест, которые я посетил.

  • Как использовать ванильный javascript внутри компонента Reactjs?
  • https://reactjs.org/docs/integrating-with-other-libraries.html

helloworld.js

var container = document.getElementById("globalArea");

var controller = new GIO.Controller(container, {
  color: {...},
  brightness: {...},
});

controller.onCountryPicked(callback);
controller.setInitCountry("FR");
controller.showOutOnly(false);
controller.showInOnly(false);

function callback(selectedCountry) {
  $("#countryArea").text(selectedCountry.name + " picked!"); $("#infoBoard").fadeIn(300);
  setTimeout(function () {
    $("#infoBoard").fadeOut(1000); }, 3000); } axios .get("./test_data.json") .then(function (response) { controller.addData(response.data); }) .catch(function (error) { console.log(error); }) .then(function () { controller.init(); }); var d3Graphs = { tiltBtnInterval: -1, }; function showHud() { $("#hudButtons").show();
  $(".tiltBtn").on("mousedown touchstart", d3Graphs.tiltBtnClick); $(".tiltBtn").on("mouseup touchend touchcancel", d3Graphs.tiltBtnMouseup);
}

function tiltBtnClick() {
  var delta;
  if ($(this).hasClass("sideViewBtn")) {
    delta = 10;
  } else {
    delta = -10;
  }
  d3Graphs.doTilt(delta);
  d3Graphs.tiltBtnInterval = setInterval(d3Graphs.doTilt, 50, delta);
}

function doTilt(delta) {
  tilt += delta * 0.01;
  tilt = constrain(tilt, 0, Math.PI / 2);
  camera.position.y = 300 * Math.sin(-tilt);
  camera.position.z = 100 + 300 * Math.cos(-tilt);
  camera.lookAt(new THREE.Vector3(0, 0, 300));
  tiltTarget = undefined;
}

............

home.html

<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <script src="./lib/jquery-3.3.1.min.js"></script>
    <script src="./lib/three.min.js"></script>
    <script src="./lib/gio.min.js"></script>
    <script src="./lib/axios.min.js"></script>
    <script src="https://d3js.org/d3.v5.js"></script>
    <script src="https://cdn.jsdelivr.net/npm/apexcharts"></script>
    <link rel="stylesheet" href="helloworld.css" />
  </head>

  <body>
    <div class="b">
      <div id="infoBoard">
        <div id="countryArea"></div>
        <div id="explanation">Infos here</div>
      </div>
      <script src="helloworld.js"></script>
    </div>
  </body>
</html>

................

Sample.js

export class Sample extends React.Component {
  componentDidMount() {
  
  }

  render() {
    return (
      <div className="App">
         ...
      </div>
    );
  }
}

Ответы

2 LionelRowe Oct 04 2020 at 18:50

Вот отправная точка. Я аннотировал части, где React взаимодействует с Gio.js.

const Globe = () => {
  // use a React ref whenever you need to directly target a DOM element
  // - this is required as an argument to the GIO.Controller constructor
  const ref = useRef(null);
  const [country, setCountry] = useState(initCountry);

  useEffect(() => {
    // useEffect with empty dependency array
    // - this will run once when the component mounts
    const controller = new GIO.Controller(ref.current, {
      control: {
        initCountry
      }
    });

    // import and add data here if you want the glowing lines
    controller.addData([]);

    controller.init();

    // here's the callback for when the user clicks a country
    // we can use the React setState hook inside the callback
    controller.onCountryPicked((country) => {
      setCountry(country.ISOCode);
    });
  }, []);

  return (
    <>
      <div>
        <strong>Selected country: {displayName.of(country)}</strong>
      </div>
      <div style={{ height: 500 }} ref={ref}></div>
    </>
  );
};

Демо CodeSandbox

PsiKai Oct 01 2020 at 17:56

Если вы поместите свой ванильный javascript-файл на тот же иерархический уровень, что и ваш, index.htmlи свяжете его обычно, вы сможете реализовать свой ванильный javascript-файл, не мешая вашему реагирующему javascript. Просто свяжите его внизу, как обычно, с помощью <script>тега.

В качестве альтернативы, чтобы использовать useStateв вашем коде реакции:

import React, {useState} from "react";
import ReactDOM from "react-dom";

const Country = () => {
  const [country, setCountry] = useState('');

  ///your javascript here

  setCountry(//return from javascript function// );

  return (
     <h1>{country}</h1>
  )
}

ReactDOM.render(<Country/>, document.getElementById("countryArea"));

Вам нужно будет импортировать axiosв этот файл любые дополнительные зависимости для вашего обычного javascript (например ).