Paul Henschel chats with Kent about building dynamic scene graphs declaratively with re-usable components and react-three-fiber to create high-performance 3D animations.

Transcript

Kent C Dodds: 0:00 Hi everyone. My name is Kent C Dodds, and I'm super thrilled to be joined with my new friend here, Paul Henschel. Say, "Hi," Paul.

Paul Henschel: 0:08 Hi.

Kent: 0:09 Paul and I, we actually haven't interacted a ton, but I followed you on Twitter for the last year or two. I've just been blown away by the really cool stuff that you've been building with React-three-fiber.

0:25 It wasn't always that. You were doing some 3D stuff with React before that custom renderer was a thing. Is that right? Maybe it was harder to write a custom renderer back when you started. Is that right?

Paul: 0:38 Yeah, exactly. It's something that started because of my work. We do like industrial designs and stuff that does CAD. It just became too complex. I was always making URI in React, but the other stuff that had to do with 3D I just couldn't or it didn't really fit in well, so I had these both clashing things that I wanted to reconcile somehow. That's how the renderer started.

Kent: 1:09 I see. This was before making custom renderers was a supported thing by React, right? This was several years ago, right?

Paul: 1:18 No, actually not. I did write a custom reconciler before. That was before, I think, React 16 or whatever. Fiber, I guess they call it. No, I waited until this thing was public. I think it started in a GitHub issue, and some people developed it further. I followed it, and eventually, they made a prerelease for beta testing. I thought, "This was it. This can solve all my problems."

Kent: 1:51 Awesome, awesome. Before we get too far down that train, I want to just get to know you a little bit. Do you want to tell us who you are, where you come from, where you work, and all that? Whatever else you want to say.

Paul: 2:08 I'm in Germany, but I work in Switzerland. I'm developing open-source for several years now. It started actually with Android. I got some smartphone. The first one that I ever got was an Android, and I started hacking.

2:27 This sparked the interest in me to develop something that other people like. We had some huge project out there that doesn't matter now. Eventually, it got a little bit hard and all the issues came in. I saw myself working day and night, so I stopped open-source for several years. I guess React, again it like rekindled my interest. Coding was fun again.

2:58 I could prototype quickly and everything I did like at home, in private or at the company, I thought, "If there's anyone that could reuse this idea, I will make it an open-source library." The first one that I published was React-spring. Then followed Use-Gesture, [inaudible] , all the others. Most of what you see on the React-spring are GitHub organization.

3:28 All these were simple little ideas that I started at work. They're super nice. They gave me permission. They said, "OK, it benefits them," and it benefits me, because I get to have some fun. Now, most of my work, I guess is in the open-source, which is a little bit unusual. That's what I do nowadays, mostly open-source.

Kent: 3:55 That's awesome that your work lets you do that. Are these projects that you're using at work as well, and so that's why there's a synergy there or whatever?

Paul: 4:06 Exactly. That's the idea behind it. Everything I develop it eventually helps, there was a problem that we couldn't solve or something had to be made easier for us. This is how it started. Yes, of course, all our products they are based on the stuff that I'm doing in open-source. Like, React-three-fiber, mainly, React-spring, [inaudible] , they're all employed in our company work.

Kent: 4:35 That was pretty similar to the open-source that I did when I was at PayPal was because we were using those things at PayPal. It's nice when the company is open-minded enough to realize that it doesn't matter where the code goes, like where it's hosted, it just matters that it's furthering our mission.

Paul: 4:55 I agree, awesome.

Kent: 4:57 That's great. You mentioned that you started coding and you fell out of interest or things just became overwhelming and you came back into it when React became popular. You said React made it fun again. What was it about React do you think that rekindled the interest in coding for you?

Paul: 5:19 It just suits my mental model. I've done lots of frameworks before, like Angular, Vue, some others before that, but I always thought that all the boilerplate or certain structures, it didn't suit me pretty well. I had an idea in my head and I just couldn't just go and implement it, so coding was [inaudible] like a burden. That's how I felt.

5:55 React, I don't know what happened. I mean in the beginning I was totally against it. I saw in JASIC, like so many got this kind of JASIC shock. I thought, "What the hell is this?" I couldn't read or parse the components, because at this time I didn't actually know what is a real component. I was just dealing with directors, and all this stuff.

Kent: 6:20 Right.

Paul: 6:20 It was pretty new and it eventually became so big that I couldn't avoid it. I tried, and it just blew my mind. I saw I think on Egghead, the first one that I saw, "Starting React," or something like this it was called.

6:37 In the middle of this video, it was like half an hour, I pressed pause. I stopped it. I closed down the tab, opened a React project like they suggested and I just could go. It was amazing to me.

6:54 I mean I had to really study Angular like I don't know weeks or months to learn the API by memory and all this just vanished and just after a couple of APIs, I could utilize them and that felt really good. I immediately liked it.

Kent: 7:13 Yeah, I tend to agree with that. React's API surface area is quite small relative to other frameworks, but I think there's an argument to be made for, "Part of the reason for that is because React is such a small portion of what you need for a bigger application." What are your thoughts on that?

Paul: 7:35 Actually, it resonates with me because I value simplicity more than anything else. I think that if you have like a stack or a piece of software, it should just do one thing and it should do it well like Unix's philosophy. At least in my opinion, React is particularly good at doing this. It's a view, it's made by function, the logic is there. State is cut off from it. It's pretty genius to me.

Kent: 8:13 Yeah, I agree. I think it's awesome. That's great.

Paul: 8:16 I also think that there are some things that you can see in the React ecosystem that just doesn't happen elsewhere, like the insane amount of packages, tools, libraries that people create. It just doesn't exist like this in other spaces and other frameworks.

8:35 I think this is one of the reasons. I mean React doesn't dictate, for instance, router, animation whatever. All these things if you wanted to fixate them, I think essentially what you are doing is stopping innovation, because requirements or our needs, all this progresses on a daily basis. React doesn't do it. Hence, the ecosystem flourishes I think.

Kent: 9:03 Yeah, I actually would agree with that. Yesterday, there was a thread where people were comparing external contributors to the React project versus how many external contributors there are on other frameworks. Somebody gave a couple of reasons why that might be, which seem to make some sense.

9:23 I replied with an additional reason, which is that React has just taken this one slice of what an application needs and just says, "We're going to work on this by itself," and that's like the core.

9:37 If you're comparing it to Angular, this would be the core template, whatever. I don't know what they call those things, but like external contributors typically don't contribute to that portion of Angular, they contribute to all the stuff around it.

9:54 Because React doesn't try to solve those other problems, there aren't as many contributors to the core, but like overall in the ecosystem, there are vast amounts of contributors to the extra stuff that you would typically need for a React app.

Paul: 10:13 Yeah, I agree. Also, I'm not sure, I guess, there's something to be said about design choices, vision, and I think one of the principles of React is to just be a abstract component standard. I think that may just have been contributing to its success.

10:38 I mean React is everywhere. I guess people don't want to see it like this right now because it's still Web- focused, but at least for the stuff that I'm doing, I'm mostly aware that React happens everywhere. This should be cherished. If you start to implement high-level abstracts or worse, platform abstracts into React, I don't think it's a good thing because you're tying it to a particular platform.

11:08 I'm not sure, I think it's pretty nice as it is. Also, if there's really something that you're looking for, mostly like one established choice, for routing or whatever and if not, then all the better.

Kent: 11:26 Right, yeah. The cool thing is that because it's not built-in, people work on the problem and there is a huge amount of people. Whereas if React did decide to bake things in, then people wouldn't work on the problem, they'd work around the problems that are in the built-in version, right?

Paul: 11:47 Yeah.

Kent: 11:48 It's possible to use a different animation library with Vue, or a different router, or whatever, but people don't because there's a built-in solution and if it doesn't quite work for them, then they'll just find ways to work around it. Whereas if it's not built in, then people are more encouraged to build their own solution and that's where the innovation comes in.

Paul: 12:11 Yeah, exactly. I'm not sure if you're aware of Popmotion, I guess, Framer Motion, for sure, but the predecessor was Popmotion, and the guy Matt Perry, I think, he tried it because he got request. People said, "OK, we want it also for Vue, and we want it for a Vanilla JS," and so on.

12:35 He split his efforts into pieces and he starts offering his library for the Vue ecosystem, the space, but I don't know, I saw the MPM stats and it was pretty crazy because Popmotion is a huge library in React, but for Vue, no one is using it.

12:57 You see the same mostly replicated for all the popular libraries that exist in the React space. Some may exist like static components, and so on, but no one's really using it because they have one baked-in solution and this solution may work for some people, but may also be very limited for others.

13:16 This is what I really love about React. Also, I think we have all seen how this model to bake things in can go wrong, like with the Web. They had so many specs that didn't work out. Now, everyone's against Web components because they don't fulfill requirements, or whatever.

13:38 I don't want to get into this, but you just see that something's wrong, someone sits down in a meeting room like 10 years ago and decides some high-level thing, but everything, our environment changes and our requirements and needs and then this thing that I developed just doesn't hold. It doesn't suit. That's the danger of this model.

Kent: 14:01 Yeah, absolutely. One of the cool things, as you were saying earlier, that's really impressive about React is its ability to be just this thin abstraction of a component model. That component model can be used all over the place.

14:22 You are one of the people who have taken it beyond just the DOM and put it into something greater. I'd love to talk about that specifically like Three.js 3D in the browser.

14:36 One thing in particular that I'm interested in is, "What was it that made you decide to reach for React for this?" I know that especially for things like 3D, or graphing, or things with lots of parts, people are always screaming, "React is slow." Why would you use React for something like this?

Paul: 15:00 Yeah, I know this very well.

15:02 [laughter]

Paul: 15:04 I don't know, I just recognized that the same problems that we're solving with React for the DOM, it just applies to everything. Actually, before I thought like a game would be completely different, it would be irrational using React for something like this, or really just anything that is in DOM.

15:30 Now, I'm pretty convinced that that was foolish. The problems are the same. A game is essentially a state engine, a state machine. Like everything else, like forms, and really React takes something, makes a component out of it. It's self-managed.

15:52 You can reutilize it everywhere you want. It's completely encapsulated. That's pretty great. I actually think that for something like Three.js, it actually makes more sense than a DOM because Three.js, as I said often, "It's not principled. It's like very far out. There are so many objects you need to keep track of."

16:16 It's not like the DOM, you create one little thing, it's a div and then you put it in there. You say, "Parent," and then it's in there. It's not like Three.js works. You have something and this something is wired into everything else.

16:28 You have set up, you have render loop, you have resize, you have events. This little thing that you created, let's say a visual primitive could be a box or whatever, it's everywhere in your code base.

16:40 If you've ever seen Three.js snippets and examples, they're the same. They're unreadable, because everything is connected to everything. Yeah, React just completely solves it just like it did with the DOM, but here it's even more maybe apparent, I don't know if that's the right word.

17:03 You can really see the code shrinking. In a DOM, it's also large but in Three.js, I think in the end, if you have a big application, you can cut out like 70 percent or something.

Kent: 17:15 Wow.

Paul: 17:16 It's a lot cleaner, as well.

Kent: 17:20 Yeah. You take this library that has an imperative API by design and probably would struggle to not have an imperative API. At some point, there's got to be some imperativeness, like at some level of the abstraction, eventually we're going to get to zeros and ones, [laughs] but you were able to put a declarative API on top of that.

Paul: 17:44 I think it's even both, because there were things like this before. They used React, they've wrapped every component of Three.js. [inaudible] , so it's not a renderer. They have like 300, 400 components.

17:57 It's impossible to maintain, but this whole thing just blurts out some static graphs. It's pretty, I don't want to say useless, because someone's made it, but we just didn't think it would suit our needs.

18:16 The imperative nature is super important. You need reference to the actual things that you made, a mesh, whatever. You also need to be able to mutate it, to animate it. You don't do this declaratively. This is something we have learned with animated and we have made it with React-spring. Framer Motion has picked us up, so it's a pretty useful thing.

18:42 There's no real means in React for this, but lots of libraries they have seen that some things they need are the imperative nature. This is perfect with software hooks. There's one hook in particular, it's called useFrame in React-three-fiber. This allows a component to hook into the render loop so you can spin around something, whatever.

19:10 If this component unmounts, it takes out this effect. Even that is self-managed. Before this, I'm sure you have heard of a game loop, right?

Kent: 19:21 Yes.

Paul: 19:22 A huge encompassing loop where everything is happening. Basically, it's a [inaudible] , because it needs to know about everything. This is broken up in React with hooks. You have the declarative nature, the graph, the tree is written out like this, but you can interact on it, mutate stuff, in a safe way of course, through hooks, which is pretty crazy. Before hooks, React-three-fiber wouldn't have been possible.

Kent: 19:55 Hooks were definitely in the category of enabling technologies. I haven't used to React-three-fiber. This could maybe reveal some of that for you, but I'm curious with the tree structure of the React component model. How does that map to a 3D thing that you're trying to create?

20:24 I'm also interested in this from a VR perspective as well, because it's a very similar type of environment. We've got a 3D environment that is nothing like a tree structure, but then we're writing our code in a tree structure. How does that work?

Paul: 20:39 The fun thing is, let's say a tree structure even in Three.js, you have something like a scene, think of it in DOM terms as your body, like a container element, or whatever. Then you just put stuff in it. You put in a mesh. A mesh describes something that's visual. This mesh has a geometry. It's all you can think as little nodes and you have scene, you have the mesh, the mesh contains a geometry.

21:11 Geometry defines what it is, how it looks like, or not how it looks like, the form and the volume. It could be a sphere. I don't know, it could be complex model. Then you have a material, which is also part of the mesh. Material says, "This thing's red," or, "This thing is shiny." You just build lots of these little nodes. Basically, it's the same as divs and spans, it's just different parameters.

Kent: 21:43 Do you typically see a lot of nesting happening? One thing that I'm thinking about is let's say that you're writing some animation of different balls floating around. You can structure that where each ball is just a direct child of that scene, but, then you decide you want one of the balls to break into multiple other balls or something like that. Would you just think ahead and have an individual ball for...?

22:21 I don't know, I'm just trying to see how I could structure that. Normally, I would say, "I have this one thing, and then there are things inside of it, so I'll nest those in there." If I want those things to come out of that, then I would need to change where they're being rendered. Maybe this question isn't making sense. I'm not sure if you can make sense of that.

Paul: 22:42 It makes sense. The mistake that you might make is that you think of Three.js or whatever as something completely different than a DOM. It's really not. It's the same principle. You have a div with a sidebar, you load in a component. If this component is generic enough, you say, "I make it my master, and I can reuse it like a button."

23:09 If it's not so generic, then it's just a parental component, like something that encapsulates several buttons or whatever. It's also the same thing in the 3D space. These things they can have children. Actually, if you know what a mesh is, a geometry and a sphere, a material, you could just go on to build like basic stuff. The rules and principles, they're the same, exactly the same like in a DOM.

Kent: 23:45 That just makes me want to go build something. That's very cool.

Paul: 23:48 Yeah, you could. You should try it.

Kent: 23:51 This is one of the beauties of React is that there are a couple of awesome side effects to this. React can be used anywhere. You've got VR native and Three.js. There's Ink, which is a renderer for the terminal.

24:06 It's amazing where we can take this component model, and so because of that, two things happen, I, as a Web developer, can now enter these other spaces that I would have no business in otherwise and then people who are already in those spaces, can now use these superior tools for modeling these kinds of things.

24:28 Then, once they've learned it there, they can now start moving all over, so you get this cross-pollination of really interesting ideas.

Paul: 24:35 Yes. I think it's even crazier than this. Again, this is all like frontier stuff, like not so many people are involved with custom renderers. If you are, you notice certain patterns.

24:52 For instance, one of the things that immediately blew my mind is that I noticed I can use any React library that I want, because React, like imagine an animation library, it does not animate divs and spans, it animates React components.

25:12 Immediately, you take something out of the React ecosystem, and you say, "Now you animate in Ink." What do they have, boxes?

Kent: 25:25 Yeah.

Paul: 25:25 I have not used a lot of Ink, but you just code and this amazing or let it be a mesh. You can rotate or change color or whatever.

25:34 There's this cross-pollination, unlike everything I've seen before, because in Three.js or in all these contained platforms and ecosystems, they just have theirs. There's a couple of people working on this. It's not so big. If they want to animate something, something has to be specifically made for this purpose, but in React everything handles or deals with the components itself. This is magical to me.

Kent: 26:05 That is mind-blowing. Especially with hooks. Before hooks, it was a lot harder to do this kind of cross-pollination or code sharing.

Paul: 26:16 Exactly.

Kent: 26:19 This is good stuff. For folks who are watching, definitely go take a look at the React-three-fiber GitHub repo, because there's a bunch of demos of amazing things. I'm like, "There's no way that React built this," but apparently you can do this with React.

26:39 I'm curious, where do you get your designs and materials and different things like that, your assets, 3D assets? If I decide I want to go build something, I'll probably start with just moving spheres around or spinning boxes and stuff. If I wanted to actually build something legit, where do you typically go to get those kinds of assets?

Paul: 27:06 It depends on what you want to make. I guess most people think of something like gimmicky, like a 3D game of flying dragons or whatever, but it doesn't even have to be like this. Have you ever seen, I never know how to pronounce this website, A-W-W-W, Awwwards?

Kent: 27:28 I don't know. Yeah, Awwwards.

Paul: 27:30 I'm sure you've seen on it all these crazy websites that you just know you just couldn't replicate. They're wobbling stuff around, like flying planes made by these crazy design agencies. You don't need dragons and fireballs for this. It's just meshes, planes, images, but you have the added benefit of having a camera.

28:00 It can be a perspective camera, you have the zet access, or you have natural parallax, you have shaders, all these things are now possible. If you want to make a game, there's so many places you can get models from, Google, Poly.google. I think Polygon, I don't know. Most people find that. I forgot the name.

28:34 There's also Sketchfab, which is also pretty cool, so lots of places where you can just download ready-made models. If you really want to dig in, you can learn Blender. It's a horribly complex software.

28:51 I tried to learn it, followed some tutorials. I can do some basic stuff, but I basically gave up. For what I want to do, it's enough. It's amazing what you can do with it, because this will actually enable you to make real games. There's so many assets there that you can do like ready-mades skeletons, I think they call it.

29:16 You make your own model, you put a skeleton on it and then you can download movements and all this stuff. This is if want to make a game. I'm not so into games. I tried. I made actually a couple. They also in this GitHub repo, but I'm more interested in the frontend space. There are so many great designers in the React space. They make amazing things, but still limited by what the DOM can do.

29:45 The DOM is also very slow. The DOM chokes if you try to shift 10 divs across the screen. There's always lag. Matt Perry, recently on Twitter, he said that browser window, vendors even have throttled requestAnimationFrame, or something like this. It's pretty terrible. The DOM is slow. It always looks bland.

30:15 The only thing you can hype it up is with great layouts, typography and so on. If you really want to go overboard, over the edge, then you can get shaders and the craziest stuff. This is possible in Three.js, pretty easy actually.

Kent: 30:36 I'm curious also, when we're doing 3D stuff, how do you make that accessible? Can you with like a screen reader? Are there any API's for that? Correct me if I'm wrong, but this is built on top of WebGL, right? That's what Three.js is working with. Are there WebGL primitives for accessibility?

Paul: 31:00 No.

Kent: 31:01 Yeah, that really clinks it. That's too bad.

Paul: 31:06 It's possible. If you go to these professionally made agency websites, they have it. They only get it by mixing the DOM and WebGL, which is very interesting to me. This is what I'm trying to do for the last couple of months, to establish better tooling for this, because there's only a couple of people that can actually do this. It would be great to give out something that everyone can use.

31:33 As you know, the Web is like a bunch of random tools they bolt on, they try something out. Maybe the spec is established, but they just forgot accessibility. I think the entire canvas has a role, and that's about it. It's like BlackBox. If you start mixing stuff, you can make possible ones. From Twitter, I had a couple of demos, it's not so hard with React-three-fiber.

32:04 We also developed some things that help. There's a library that we made called Drei. It's German for three, and has lots of helpers and so on. This one allows you to easily bind HTML to a Three.js component. Now you can separate between visuals for graphics, and layout and typography. People can select with their cursors and screen views, can get roles and so on, but behind some crazy shader stuff.

32:40 At least, this is possible. In the super, super professional sites I've seen, even the graphics, they just put an invisible div on top of it, or something like this. It has role. It's accessible to screen readers. There's arts, text content. Yeah, it's possible but it's all a workaround, because the spec doesn't do it.

Kent: 33:09 Yeah, that makes sense. I can imagine that some things you really couldn't make accessible, like a game. That would be a very difficult thing to make accessible [inaudible] people.

Paul: 33:24 Also, I'm not sure if it makes sense because you have depth.

Kent: 33:28 Yeah, that would be extremely difficult. That's tough. I'm coming down to the last little bit of things I was curious about for now, before I dive in. You'll probably never hear the end of me if I jump in. What about automated testing? Is there any reasonable way to test your React-three-fiber components that I write?

Paul: 33:58 Yes. It's the same. You can use just Jest and that's about it. You can make snapshot testing, unit testing, whatever you want. You don't need something like React Testing Library. I'm not so well acquainted with this stuff, but I think something like Enzyme and React Testing Library emulate the DOM, right?

Kent: 34:23 Right.

Paul: 34:25 Nodes doesn't have this [inaudible] ?

Kent: 34:27 Technically, it's JS DOM that emulates the DOM, so React Testing Library might be run in a real browser, but, yeah, it relies on the DOM, for sure.

Paul: 34:37 You don't need this because in Three.js everything is there. It runs nodes, it solves testing on Jest. It has no problems at all. You don't need some additional thing, just the renderer or reconciler, whatever it's called these days, and Jest, and that's it. There's no proper tooling, but you can still dive in and find stuff through children and there's find methods and stuff like this with Three.js. I think it's pretty easy.

Kent: 35:15 Do you have examples of tests that you've written?

Paul: 35:19 Yes. In the directory fiber repo, there's testing. I have not had the time to really explore it, but there's a basic snapshot test that shows you how to do it. I think there's not much to it. You can prove me wrong, but I don't know.

Kent: 35:44 Well, is there is anything else about React-three-fiber or React in general that you wanted to talk about before we wrap up?

Paul: 35:54 I'm not so sure. Just that we're working. Maybe this, that we're working right now on several tools coming up. One is a flexbox tool. This is a huge problem that you have your 3D content, but it's not responsible, responsive.

Kent: 36:15 Responsive.

Paul: 36:16 Sorry, my German coming in between. That solves that with real flexbox, which is amazing. You can have layouts, and it's responsive, adapts to browser width, and so on.

36:35 Generally, we are trying now to more go into the frontend dev thing. Lots of new things will come out very soon to make it easier for people to explore this 3D thing without thinking that it's just a gimmick for games, or whatever. That's pretty important to us to really give it into the hands of just regular frontend devs on the DOM.

Kent: 37:02 That's awesome. Actually one other thing I'm curious about. The typical use case for something like React-three-fiber is within a React application. Like I'd have my surrounding stuff that's just DOM, and then within that there's a window of WebGL, whatever.

37:22 How does that integration typically work? We've got ReactDOMrendering, everything. Would I have a component that has a renderer with React-three-fiber within a useEffect or something like that?

Paul: 37:38 Right now, yes. You have components called canvas. You just drop it in into your ReactDOM tree structure and everything that resides within is rendered out by the React-three-fiber renderer so the mesh is one. In the upcoming version, we're going to split this so you have both.

38:01 You can export render, just like ReactDOM.render. You can say Rectifiable.render. You can do stuff without relying on the DOM, because it's 40 kilowatts these days. You can shave that off, if you don't need it.

Kent: 38:20 Sure. If you had an application that was 100 percent 3d, you just...?

38:25 [crosstalk]

Kent: 38:25 Yeah, that makes sense. Very cool. Thank you so much for giving us some of your time to talk about this frankly, really amazing stuff. I'm excited now to try actually building something. I remember I did a Hello World in React VR. It blew my mind that it was so easy to do that and using the same simple primitives that I'm used to from React. I will try this out.

38:54 Maybe I'll do a super simple start to React-three-fiber. I like making those little blog posts. Anyway, fun stuff, man. Thank you so much for letting me have some your time and we'll see you all on the Internet.

Paul: 39:09 Thank you.

Kent: 39:10 Bye everyone.

Paul: 39:11 Bye.