A Better Way to Use Two.js in React
One of the longest running feature requests for Two.js is finally getting the attention it deserves.
The long running and fairly popular two-dimensional drawing API for the web, Two.js has received many feature requests over its 13 year lifespan. None has been requested more than adding the ability to declaratively create and manage a scene within React. For those not familiar, React is a pervasive library for web enabled application development. It allows you to manage data, state, interactions, and render it all in a highly opinionated way making it easy to manage complex applications. Two.js is and has always been agnostic to any framework. So, its compatibility with React is possible, but unconventional. Not surprising, the requests continued to come in.

I am the kind of developer who does not adopt frameworks, libraries, or plugins at the speed they are released. I am also someone who makes their living out of creating “unorthodox user-interfaces” for the web, not building the most common ones. I initially did not see the need to take on building out a React connector. I thought if someone else did, that would be great for the community. In 2021, this perspective changed.
As I dug into the meat-and-potatoes of running a solo studio, I found myself needing to build a lot of “orthodox user-interfaces” for clients. Buttons, drop down menus, sidebars, navigations, toasts, marquees are some of the components I was making over and over again. They were still in service of unorthodox user-interfaces, but I needed more and more of the common stuff in order to frame the unorthodox, the weird, the unexpected. All my clients wanted their work built in React.1 They also, more often than not, wanted me to add that special something that Two.js made my work famous for. A couple projects I published on Soup to Software are attempts to write, manage, and build out Two.js interfaces within React.2 I’m proud of these projects, but I hit a ceiling. I learned it was complicated and cumbersome to pass around state information of Two.js within a React project. As you can read in the aforementioned posts, both projects I wrote about are single page applications (known as SPAs). They run on a single page without any user authentication in part because of the challenges managing Two.js within React presented. There had to be something I could do about this, right? The needs of applications and application development today continue to lean on complex scenarios of state.
In order to fully assimilate Two.js into React, there were two major hurdles to overcome. The first hurdle, React is technically a project made in JavaScript, but its true ubiquity lies in its interoperability with TypeScript. TypeScript is a superset of JavaScript. It is more strict and as result it is more predictable. React relies on numerous advancements by the TypeScript community to infer developer intent when building applications. Some of these advanced features are tab completion or module imports and reference listings of properties within code editors. These features make writing compliant code easier. Unfortunately, Two.js takes advantage of many of quirks of JavaScript. This is more expressive and less predictable (for a code compiler). This made it hard to make Two.js conform to TypeScript definitions. Type definitions or signatures are the way a TypeScript interpreter can do code inferencing while a developer is writing their code. To reiterate, my first hurdle was to make Two.js TypeScript compliant. It is still an ongoing project and it has taken me about four years to manually write the type definitions for Two.js.
You are probably thinking, why not use AI to do this? I tried many times. It always failed. Because Two.js leans on the quirks of JavaScript, it does not cleanly map onto TypeScript even though TypeScript is a superset of JavaScript. I ended up writing it myself manually; 6,000 line treatise of Two.js.3 What I found through hand writing the definitions, while slow, is that I am actually able to bring the quirkiness of Two.js to TypeScript. It is not fully complete, but it is usable for the majority of use cases I see people use Two.js for.
With the TypeScript definitions in a stable form, it became much easier to write a library that bridges React and Two.js. This is the new library I am announcing today: react-two.js. It takes the type signatures of Two.js and synthesizes it into artificial React components so that developers can declare Two.js objects as if they were declaring native React components. By bridging the state management between the two distinct systems, react-two.js unlocks the ability to build new kinds of interfaces.
Buttons with particles, wireframes with form input fields, animated titles like you would see in a film. Each of these is now possible within a React environment thanks to this new bridge. This first version allows for drawing all the primitives natively in React. You can easily hoist them in a parent component to modify as desired on state change. Lastly, it provides React native ways to define multiple Two.js canvases on the same page. There are still many features missing, but full access to Two.js is always present for more advanced use cases. I have already started using this within client projects and it has sped up my workflow tremendously.
Like all my open source projects, it is free to use under the MIT License. If you give it a try, I would love to get your feedback,
–Jono
Not literally all, but since 2021 more than 90% of my client projects are built in React.
https://github.com/jonobr1/two.js/blob/dev/types.d.ts. Ongoing TypeScript definitions of Two.js.




