Open jugglingcats opened 8 years ago
My error was due to using wrong THREE version, so that is resolved.
I also managed to get TS compile errors to be reduced significantly by adding the following to my code:
declare global {
namespace JSX {
interface IntrinsicElements {
scene: any;
perspectiveCamera: any;
ambientLight: any;
axisHelper: any;
// other elements can be added here
}
}
}
Note that Typescript treats component names in JSX with lowercase as 'intrinsic', ie. expects them to be HTML and not React components.
I still have an error on compiling about missing module "react-three-component" but Webpack is including it and my app is running.
Perhaps others can add Typescript specific help/workarounds to this thread. Would be good to see first class Typescript support at some point!
Regarding lower case components being html perhaps we could extend the definitions or something to accept custom "native types", I think that would be awesome for prop type verification on compile time!
Currently the main priority of the project is to have full feature compatibility with threejs on latest react, but it would still be awesome to see it working nicely with TS :) let's keep the issue open until then, could be a fun one.
On Thu, Nov 17, 2016, 20:57 jugglingcats notifications@github.com wrote:
My error was due to using wrong THREE version, so that is resolved.
I also managed to get TS compile errors to be reduced significantly by adding the following to my code:
declare global { namespace JSX { interface IntrinsicElements { scene: any; perspectiveCamera: any; ambientLight: any; axisHelper: any; // other elements can be added here } } }
Note that Typescript treats component names in JSX with lowercase as 'intrinsic', ie. expects them to be HTML and not React components.
I still have an error on compiling about missing module "react-three-component" but Webpack is including it and my app is running.
Perhaps others can add Typescript specific help/workarounds to this thread. Would be good to see first class Typescript support at some point!
— You are receiving this because you are subscribed to this thread. Reply to this email directly, view it on GitHub https://github.com/toxicFork/react-three-renderer/issues/127#issuecomment-261367274, or mute the thread https://github.com/notifications/unsubscribe-auth/AA0iLY1tdbnYIMhkJMsdBeCvhjbIUWByks5q_L_HgaJpZM4K1o39 .
I agree it would be great to have prop/attribute validation and auto-complete in the IDE and this is one of the main benefits of using Typescript IMO.
I am not sure adding elements to JSX.IntrinsicElements is the way to go, because of possible conflicts with other libs (you would effectively be polluting a shared namespace). I think ultimately you might consider providing initial-caps versions of react-three-renderer components, ie. Scene, PerspectiveCamera and so on. These could either be used as <React3.Scene>
or aliased during import.
Just my 2p
For info I already found a name clash: line
is defined as type React.SVGProps
.
It runs :) but compiler and IDE complain :(
I think things would need to be context sensitive somehow as new renderers emerge. Could do an annotation to a file or the render function for example to specify what sort of renderer will be used for a component.
I don't understand very much about renderers, but presumably a single component could use React3 and SVG, eg:
render() {
return (<div>
<svg><line ... /></svg>
<React3>
...
<line ... />
...
</React3>
</div>)
}
That's a bad component that should be split in half and deserves multiple warnings ;)
On Fri, Nov 18, 2016, 11:48 jugglingcats notifications@github.com wrote:
I don't understand very much about renderers, but presumably a single component could use React3 and SVG, eg:
render() { return (
) }... ... — You are receiving this because you commented.
Reply to this email directly, view it on GitHub https://github.com/toxicFork/react-three-renderer/issues/127#issuecomment-261514142, or mute the thread https://github.com/notifications/unsubscribe-auth/AA0iLVZVWYGeFkzGqZatPPn1qoP-lxm1ks5q_ZCfgaJpZM4K1o39 .
Heheh. I tend to agree!
I thought more about what you said and I think what you need is a way to say "The React3 component doesn't contain JSX.IntrinsicElements but instead contains React3.IntrinsicElements". That would be a nice solution.
I just came across this thread. I came up with a slightly different approach that doesn't involve having to extend JSX.IntrinsicElements
but gives you all the type safety. It involves a bit of work creating wrapper elements. But honestly, I think these are probably as much work as creating a .d.ts
file.
First, I we have to import React3
. I was wrestling with TS2+'s augmentation stuff and couldn't get it to work. So I just punted and did this at the top of my file:
let React3: React.StatelessComponent<React3Props> = require('react-three-renderer');
...and I defined React3Props
as:
export interface React3Props {
mainCamera: string;
width: number;
height: number;
onAnimate?: () => void;
}
I'm sure there is more, but this is all I'm using so far. Then you have the issue of getting that stuff out of IntrinsicElements
. I managed that by creating wrapper classes like this:
export interface PerspectiveCameraProps {
name: string;
fov: number;
aspect: number;
near: number;
far: number;
position: THREE.Vector;
}
export class PerspectiveCamera extends React.Component<PerspectiveCameraProps,void> {
render() {
return React.createElement("perspectiveCamera", { ...this.props });
}
}
Now you've got a component that the TS compiler recognizes as a first class component. This means you can then do:
<PerspectiveCamera
name="camera"
fov={75}
aspect={this.props.width / this.props.height}
near={0.1}
far={1000}
position={this.cameraPosition}/>
Now this may seem like a lot of work. But like I said, I'm not sure it is any more work than writing a normal .d.ts
file. A slight advantage that this has, I suppose, is that it doesn't require react-three-renderer
to change anything about its conventions. As far as I can tell, what the author was going for was a direct mapping between his components and the underlying THREE.*
functions (which have lower case names). So this is just layering on top of that things that are more like first class React (class-based) components that can be composed just like the react-three-renderer
components but with increased type safety.
Thoughts?
Interesting approach...!
I assume it works fine when you have nested react-three-renderer components, even though you are introducing an intermediate element into the component tree?
There would be a small performance overhead but I don't see this being an issue.
I guess one disadvantage is that this would likely be a separate project and cannot easily become a first class citizen, ie. part of the react-three-renderer project in the way that .d.ts
definitions could.
I just posted this question to SO as a last attempt to find a "pure" solution: http://stackoverflow.com/questions/43493059/react-typescript-custom-renderer-and-jsx-intrinsicelements.
If we adopt this approach, would you be willing to host the project...? Or maybe @toxicFork would be willing to make it a companion project to react-three-renderer.
The intermediate elements don't really seem to cause any problems with the exception of <scene>
. I'm not sure why, but that one doesn't want to be wrapped. Perhaps there is some logic somewhere that insists it be a direct child of the root. Not sure. For the others, I've successfully created "intermediate" elements that are nice first class react components (with their own typed properties, etc).
I agree, there is a small overhead. Note that, as far as I can tell, anytime you'd like to group things into reusable components, you'd introduce just about the same overhead. I'm just forcing each leaf in the tree to be a reusable component. There is both the overhead of the function call as well as the overhead of traversing a deeper tree. Perhaps there are other concerns as well.
I'm not sure how the "mounting" vs. "rendering" stuff is handled internally in R3R. My hope is that it is using the virtual DOM approach to optimize (i.e., minimize) manipulations of the 3D scene. If so, that might help. If not, then it would perhaps amplify any inefficiencies introduced here.
You are correct that it would probably be a separate project. You could, of course, include all this in R3R itself. But I'm guessing the author doesn't want that headache. I would have preferred the .d.ts
approach myself, to be clear. But since that seems very difficult in this case because of the conventions followed by R3R and TS, this was the best I could come up with.
As for "hosting" it, I'd certainly be willing to make it publicly available. I make no promises on completeness or maintenance. I don't expect to be using this extensively in the future. So I can't say I'd be able to do all the greens keeping some might expect. Perhaps @toxicFork can chime in with his opinions before we really make any decisions here.
Cool solutions :)
I would prefer a comment / .d.ts
based solution even if it takes more work because I am against overheads in general. However, there are ways to solve the overhead problem, for example we could (with some effort) write a babel (or whatever compiler) pre/post process plugin to convert these back into native components.
I think it would be good to have it as a separate project if possible (so you will have authority over it, issues for it won't be lost in normal r3r issues, and so on), then we can consider merging it into R3R when the time comes.
FYI, I actually gave up on my wrapper stuff. It wasn't that it was technically unsound. I just ended up opting for something that interacted directly with the THREE api rather than representing the data declaratively in JSX.
This doesn't appear to be straightforward given the lack of @types for this lib. I have tried to force it in and ignore the typescript compiler warnings but get the following error:
Are there any plans to provide support for Typescript? Or are there any workarounds perhaps?
Thanks