Nextjs templete singleton error

SyntaxError: Named export 'MotionController' not found. The requested module '@webxr-input-profiles/motion-controllers' is a CommonJS module, which may not support all module.exports as named exports.
CommonJS modules can always be imported via the default export, for example using:

import pkg from '@webxr-input-profiles/motion-controllers';
const { fetchProfile, MotionController } = pkg;

This Simple My Script

import dynamic from 'next/dynamic'

import { type NeedleEngineProps } from '../needleEngine'
import { NewTypescript } from '@/scripts/NewTypescript';
const NeedleEngine = dynamic<NeedleEngineProps>(() => import('../needleEngine'), { ssr: false })

export default function Home() {
  const handleClick = () => {
    NewTypescript.instance.callHello();
  };

  return (
    <main>
      <h1>Home</h1>
      <button onClick={handleClick}>Click me</button>
      <NeedleEngine />
    </main>
  )
}
import { Behaviour, serializable } from "@needle-tools/engine";

// Documentation → https://docs.needle.tools/scripting

export class NewTypescript extends Behaviour {

    @serializable()
    myStringField: string = "Hello World";
    static instance : NewTypescript;
    awake(): void {
        NewTypescript.instance = this;
    }
    callHello()
    {
        console.log(this.myStringField);
    }
}

Hi oot4chi! I’m an AI powered assistant here to help you. I can provide support with Needle Engine, three.js, and basic Unity or Blender topics. Please reply with your question, and don’t forget to include your OS, Needle Engine version, and Unity or Blender version if you’re using any.

2 replies left - GPT 4O
thread_azdi6KvqGHIH9UMSQJfBWv77
Reply to this message to continue the conversation

Needle Engine v3.47.4-beta
Unity 2022.3.21f1

Thanks for the details, oot4chi!

The error you are encountering suggests that the MotionController is not being imported correctly from a CommonJS module. To resolve this, you can adjust your import statement for MotionController using the default import method. Here’s how you can modify your import statement:

import dynamic from 'next/dynamic';
import pkg from '@webxr-input-profiles/motion-controllers';
import { type NeedleEngineProps } from '../needleEngine';
import { NewTypescript } from '@/scripts/NewTypescript';

const { fetchProfile, MotionController } = pkg;
const NeedleEngine = dynamic<NeedleEngineProps>(() => import('../needleEngine'), { ssr: false });

export default function Home() {
  const handleClick = () => {
    NewTypescript.instance.callHello();
  };

  return (
    <main>
      <h1>Home</h1>
      <button onClick={handleClick}>Click me</button>
      <NeedleEngine />
    </main>
  );
}

This change ensures that you’re importing the MotionController properly, according to how CommonJS modules export their members.

If you need further assistance, feel free to ask!

1 replies left - GPT 4O
thread_azdi6KvqGHIH9UMSQJfBWv77
Reply to this message to continue the conversation

cant fix my bug.
but why.i can use NewTypescript.instance.callHello(); in NeedleEngine Component not bug.

// https://nextjs.org/docs/getting-started/react-essentials#the-use-client-directive
'use client'

const isServer = () => typeof window === `undefined`;

import "@needle-tools/engine";
import { type NeedleEngineAttributes } from "@needle-tools/engine";
import { useEffect, useState } from "react";
import { NewTypescript } from "./scripts/NewTypescript";

// Make addEventListener optional
export type NeedleEngineProps = Omit<NeedleEngineAttributes, 'addEventListener'> & { addEventListener?: (event: CustomEvent) => void };

/** **Needle Engine Component**  
 * Import with `const NeedleEngine = dynamic(() => import('./needleEngine'), { ssr: false })`
 * 
 * @example
 * <NeedleEngine src="./assets/next.glb" loading-style="light" style={{ width: '100%', height: '100%', }}></NeedleEngine>
 * 
 */
export default function NeedleEngine({ ...props }): JSX.Element {

  const [src, setSrc] = useState(props?.src)

  useEffect(() => {
    // import the codgegen to register types
    if (!isServer()) {
      import("./generated/gen")
        .then((m) => {
          if (props?.src === undefined)
            setSrc(m.needle_exported_files)
        })
        .catch((e) => {
          console.error(e)
        });
    }
    
  }, [])

  const handleClick = () => {
    NewTypescript.instance.callHello();
  };

  return (
    <>
     <button onClick={handleClick}>Click me</button>
      {!isServer() && <needle-engine src={src} {...props}></needle-engine>}
     
    </>
  );
}

Hi oot4chi!

In your NeedleEngine component, it looks like you’re trying to access NewTypescript.instance.callHello() when the button is clicked. This might lead to issues if NewTypescript.instance is not properly initialized before the button is clicked.

Here are a few adjustments to ensure that NewTypescript.instance is initialized before you attempt to call callHello:

  1. Ensure Instance Initialization: Make sure that the NewTypescript instance is created before any button click.

  2. Conditional Button Rendering: Render the button only when the instance is available.

Here’s how you can modify the NeedleEngine component:

// https://nextjs.org/docs/getting-started/react-essentials#the-use-client-directive
'use client';

const isServer = () => typeof window === `undefined`;

import "@needle-tools/engine";
import { type NeedleEngineAttributes } from "@needle-tools/engine";
import { useEffect, useState } from "react";
import { NewTypescript } from "./scripts/NewTypescript";

export type NeedleEngineProps = Omit<NeedleEngineAttributes, 'addEventListener'> & { addEventListener?: (event: CustomEvent) => void };

export default function NeedleEngine({ ...props }): JSX.Element {
  const [src, setSrc] = useState(props?.src);
  const [isInitialized, setIsInitialized] = useState(false);

  useEffect(() => {
    if (!isServer()) {
      import("./generated/gen")
        .then((m) => {
          if (props?.src === undefined)
            setSrc(m.needle_exported_files);
          
          // Initialize NewTypescript instance here.
          NewTypescript.instance = new NewTypescript();
          setIsInitialized(true); // Mark as initialized
        })
        .catch((e) => {
          console.error(e);
        });
    }
    
  }, []);

  const handleClick = () => {
    if (isInitialized) {
      NewTypescript.instance.callHello();
    } else {
      console.warn("NewTypescript instance is not initialized yet.");
    }
  };

  return (
    <>
      {isInitialized && <button onClick={handleClick}>Click me</button>}
      {!isServer() && <needle-engine src={src} {...props}></needle-engine>}
    </>
  );
}

In this modification, I’ve added an isInitialized state to track when the NewTypescript instance is ready. The button will only render if isInitialized is true, ensuring that you don’t try to call a method on an uninitialized instance.

Let me know if you need further help!

0 replies left - GPT 4O
thread_azdi6KvqGHIH9UMSQJfBWv77
Reply to this message to continue the conversation