I am playing with React Fiber and React Drei but i do not want to use Typescript like in the examples i have found in their git
I have converted the following example Stars.tsx with typescriptlang tool
This is the output
import React, { useState, useRef, useEffect, useMemo } from "react"; import { useFrame } from "@react-three/fiber"; import { Points, Vector3, Spherical, Color, AdditiveBlending, ShaderMaterial } from "three"; class StarfieldMaterial extends ShaderMaterial { constructor() { super({ uniforms: { time: { value: 0.0 }, fade: { value: 1.0 } }, vertexShader: /* glsl */ ` uniform float time; attribute float size; varying vec3 vColor; void main() { vColor = color; vec4 mvPosition = modelViewMatrix * vec4(position, 0.5); gl_PointSize = size * (30.0 / -mvPosition.z) * (3.0 + sin(mvPosition.x + 2.0 * time + 100.0)); gl_Position = projectionMatrix * mvPosition; }`, fragmentShader: /* glsl */ ` uniform sampler2D pointTexture; uniform float fade; varying vec3 vColor; void main() { float opacity = 1.0; if (fade == 1.0) { float d = distance(gl_PointCoord, vec2(0.5, 0.5)); opacity = 1.0 / (1.0 + exp(16.0 * (d - 0.25))); } gl_FragColor = vec4(vColor, opacity); #include <tonemapping_fragment> #include <encodings_fragment> }` }); } } const genStar = (r) => { return new Vector3().setFromSpherical( new Spherical( r, Math.acos(1 - Math.random() * 2), Math.random() * 2 * Math.PI ) ); }; export const Stars = React.forwardRef( ( { radius = 10, depth = 30, count = 10, saturation = 5, factor = 4, fade = false }, ref ) => { const material = useRef(StarfieldMaterial); const [position, color, size] = useMemo(() => { const positions = []; const colors = []; const sizes = Array.from( { length: count }, () => (5 + 5 * Math.random()) * factor ); const color = new Color(); let r = radius + depth; const increment = depth / count; for (let i = 0; i < count; i++) { r -= increment * Math.random(); positions.push(...genStar(r).toArray()); color.setHSL(i / count, saturation, 0.9); colors.push(color.r, color.g, color.b); } return [ new Float32Array(positions), new Float32Array(colors), new Float32Array(sizes) ]; }, [count, depth, factor, radius, saturation]); useFrame( (state) => material.current && (material.current.uniforms.time.value = state.clock.getElapsedTime()) ); const [starfieldMaterial] = useState(() => new StarfieldMaterial()); return React.createElement( "points", { ref: ref }, React.createElement( "bufferGeometry", { attach: "geometry" }, React.createElement("bufferAttribute", { attachObject: ["attributes", "position"], args: [position, 3] }), React.createElement("bufferAttribute", { attachObject: ["attributes", "color"], args: [color, 3] }), React.createElement("bufferAttribute", { attachObject: ["attributes", "size"], args: [size, 1] }) ), React.createElement("primitive", { dispose: undefined, ref: material, object: starfieldMaterial, attach: "material", blending: AdditiveBlending, "uniforms-fade-value": fade, transparent: true, vertexColors: true }) ); } );
Then i have paste this Stars component in my codesandbox
The component is now commented at the row 28 of index.js because i get the following error
Error Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: undefined. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports. Check the render method of `App`.
I do not understand exactly where the problems is with this error.
What is wrong with stars.js component that i have converted from typescript to javascript? How can i fix it?
Advertisement
Answer
Import the named Stars
, like:
import { Stars } from "./stars";
Working example: https://codesandbox.io/s/elegant-lumiere-1wf3uo