3

I'm trying to create a React page which includes a p5 sketch, but doing so seems to require me to rewrite standard JavaScript I would normally run in a browser to make it work as a react component.

For example, I'd like to have React serve this code to the client:

function setup() {
    createCanvas(600, 600);
}

function draw() {
    background(0);
}

But I can't find a way to just have React give the client a JavaScript file. Instead I have to create a component like this:

export default function(p: p5) {

    p.setup = function setup() {
        p.createCanvas(600, 600);
    };

    p.draw = function draw() {
        p.background(0);
    };

}

This might seem trivial but if my team and I can include code that we've already written which works outside of react without having to rewrite everything would make things much easier.

One way to solve the problem is to just place the file in the public directory of React and just serve it statically along with index.html, but I'd prefer to only give the client the file when it needs it instead of just serving every file at once. If I could just have a component import the JavaScript file and send it like it can do with images, that would be exactly what I'm looking for.

Edit: Sorry, to clarify what I meant, Node is what's actually serving things, what I want is when React renders a page it will also run JavaScript code as if it were written in a <script> tag in the HTML page.

VirtualParticle
  • 113
  • 1
  • 6
  • Are those functions supposed to be globally accessible? Because if so, that makes your job easier. – TKoL Nov 07 '19 at 16:37
  • If you want them to be globally accessible, put them in an object defined something like this: `window.canvasHelpers = {setup: function() {}, draw: function() {}};` in one file, and import that file in the relevant React files. – TKoL Nov 07 '19 at 16:39
  • 3
    React is... not a thing that serves pages. What exactly are you doing? – AKX Nov 07 '19 at 16:40
  • @AKX Sorry, read edit: Sorry, to clarify what I meant, Node is what's actually serving things, what I want is when React renders a page it will also run JavaScript code as if it were written in a – VirtualParticle Nov 07 '19 at 16:45
  • 1
    React doesn't generate .html pages (unless you're explicitly doing server-side rendering) - what's stopping you from adding that – AKX Nov 07 '19 at 16:46
  • You can also use react to create ` – TKoL Nov 07 '19 at 16:49
  • I am doing server-side rendering. The app just has one `index.html`. I don't want to have this script run on every page of the app, just one. – VirtualParticle Nov 07 '19 at 16:50
  • @AKX to add more what I'm essentially trying to do is have react read a JavaScript file and give it to the client in a ` – VirtualParticle Nov 07 '19 at 17:20
  • @AllTheMegahertz why is just running the code in the component itself not an option ? – Viktor Garba Nov 07 '19 at 17:37
  • @AllTheMegahertz you can also just add a function to the component that you want to run the javascript to dynamically add the script tag to the html on WillMount or the constructor – Viktor Garba Nov 07 '19 at 17:40

2 Answers2

5

I've solved it. Essentially I put all of the code I want to run in a file like sketch.js but surround it in a function which is exported:

export default function Sketch() {
    function setup() {
        createCanvas(600, 600);
    }

    function draw() {
        background(0);
    }
}

Then in app.js you can do something like:

import Sketch from './sketch';
Sketch();

That will run all of the code in that function in the client's browser.

VirtualParticle
  • 113
  • 1
  • 6
0

So just an option, we do this for optionally loading certain scripts on our app. In your component on the constructor (or maybe the willMount, play around with it) create a new script tag and append that script tag to the head of you app. This will cause the script to only be run when this component is rendered (Depending on where you called the function to add the script tag). You might also have to think about removing the script tag depending on what your doing, but you get the idea.

The function would look something like this:

addScriptTag = () => {
  script = document.createElement('script');
  script.src = [url/path of the javascript you want to server from your node server];
  // Or just set the javascript on the script tag by adding innerText and type arts
  document.head.appendChild(script)
}

then do something like:

constructor() {
  this.addScriptTag();
}
Viktor Garba
  • 303
  • 2
  • 5
  • That's almost what I want, but what that requires the JavaScript files to be in a public directory available at all times. If that `src` is equal to `p5/sketch.js` for example, it will look for `example.com/p5/sketch.js` instead of serving that file in the project directory. What I'm trying to do is give the client the file only when a component calls for it. – VirtualParticle Nov 07 '19 at 18:46
  • Yea there were a lot of parts to that question. First you kind of hinted at being concerned about it being publicly accessible. Second that is a way to access it only when the component calls for it? You would set the source equal to a url for the file in a static directory on your node server. It wouldn't be served with the bundle, only when that function addScriptTag is called – Viktor Garba Nov 07 '19 at 18:54