Rational

I needed a simple, fast 3D mesh ray-tracer in a React 16 project, and none of the few available seemed to work or fit the criteria. So, I decided to port the trusted old JSC3D library to react.

Starting out

I first made the mistake of using create-react-app to start a new component. Don't do this, as it doesn't set up your project to be easily exported as an NPM component.

Instead, I suggest using nwb which has a scaffolding script just for this. The command I ran:

nwb new react-component name-of-component

Including the legacy code

First I grabbed the legacy script in an unminified format, however concatenated into a single file. To make it easier to debug in the future, I decided to attempt to get things working with as few modifications to the legacy script as possible. Later I may start digging into modernizing the original code and adding unit tests, but for now my main goal was just wrapping it, mostly untouched.

I noticed everything about JSC3D was attached to a JSC3D object. So, to expose it in the Node module system, I added the following to the top:

The /* eslint-disable */ disables linting for the file, since the legacy code doesn't follow linting standards at all. The rest simply exposes the JSC3D to whatever requires this as a module.

Integrating with React

Rendering DOM element with reference

In order to mount the legacy code on the page, I needed React to render a <canvas> tag, and maintain a reference to it. I decided to wrap it with a div (to make styling easier) and attach a blank canvas element to this.canvas, as such:

The _setProps method I created uses the jsc3d API to update the this.viewer with the React component properties. You can see it here.

Preventing React from updating

Using the shouldComponentUpdate life-cycle method, I ensure that the this.viewer stays updated if props change (e.g., if something using this component were to change the model color or something), and also ensure that React.js doesn't overwrite the DOM:

Testing

To test / develop the code I wrote, I used the built-in demo server (with npm run start) that comes with the nwb scaffolding. First I added the media (in this case, stl 3D mesh files) to demo/public, then I edited demo/src/index.js to use my new component:

Finally, I wrote some simple tests, set up automated testing with Travis, and released it on NPM!

Debugging

During testing, I noticed it didn't properly define a few variables before use. While browser JS implementations are lenient enough to handle this, this was causing issues when compiling, so I had to specify all of them at the top of the file, like this:

Michael Bethencourt
(@mbgamedev) is
a developer based in the SF Bay Area. He blogs
about indie game development on his OS of choice,
Linux.

My Coding School

I founded a cutting-edge coding academy. If you live in the San
Francisco Bay Area, you can learn to code full-stack web development in
Python and React.js, by taking one of my affordable, intensive courses.