bamlab / react-tv-space-navigation

A React Native module to handle spatial navigation for a TV application in a 100% cross-platform way
https://bamlab.github.io/react-tv-space-navigation/
MIT License
224 stars 19 forks source link

TypeError: constructor is not callable when using SpatialNavigationRoot #115

Open jijithjv opened 7 months ago

jijithjv commented 7 months ago

Description: I am a newbie in react-native-TVOS and spatial naviagtion. I am trying to create a demo project in Apple TV. I'm encountering a TypeError: constructor is not callable error when trying to use the SpatialNavigationRoot component from the react-tv-space-navigation library in my React Native project for Apple TV. Here's the code I'm using for App.js:

import React, { useEffect } from 'react';
import { TVEventHandler, HWEvent } from 'react-native';
import { SpatialNavigation, Directions } from 'react-tv-space-navigation';
import Page from './page';

const App = () => {
  useEffect(() => {
    // Configure the remote control for Apple TV
    SpatialNavigation.configureRemoteControl({
      remoteControlSubscriber: (callback) => {
        const keyMapping = {
          right: Directions.RIGHT,
          left: Directions.LEFT,
          up: Directions.UP,
          down: Directions.DOWN,
          select: Directions.ENTER,
          menu: Directions.BACK,
        };

        const tvEventHandler = new TVEventHandler();
        const handleRemoteEvent = (_, evt) => {
          const direction = keyMapping[evt.eventType];
          if (direction) {
            callback(direction);
          }
        };

        tvEventHandler.enable(undefined, handleRemoteEvent);

        return tvEventHandler;
      },

      remoteControlUnsubscriber: (tvEventHandler) => {
        tvEventHandler.disable();
      },
    });
  }, []);

  return <Page />;
};

export default App;

Here is the code for page.js


import React, { useEffect } from 'react';
import {
  View,
  StyleSheet,
  Text,
  ScrollView,
  TouchableOpacity,
  TVEventHandler,
  HWEvent,
} from 'react-native';
import {
  SpatialNavigation,
  SpatialNavigationFocusableView,
  SpatialNavigationRoot,
  SpatialNavigationScrollView,
  SpatialNavigationView,
  Directions,
} from 'react-tv-space-navigation';

// Dummy data for rabbits
const rabbits = Array.from({ length: 20 }, (_, index) => ({
  id: index,
  name: `Rabbit ${index + 1}`,
}));

// A simple component that shows a rabbit program
const Rabbit = ({ onSelect, rabbit }) => (
  <SpatialNavigationFocusableView onSelect={() => onSelect(rabbit)}>
    {({ isFocused }) => (
      <RabbitLayout isFocused={isFocused} rabbit={rabbit} />
    )}
  </SpatialNavigationFocusableView>
);

// A sample layout for the Rabbit component
const RabbitLayout = ({ isFocused, rabbit }) => (
  <TouchableOpacity
    style={[
      styles.rabbit,
      isFocused && styles.rabbiFocused,
    ]}
  >
    <Text style={styles.rabbitText}>{rabbit.name}</Text>
  </TouchableOpacity>
);

// Component for a row of rabbits
const RabbitRow = () => (
  <SpatialNavigationScrollView horizontal>
    <SpatialNavigationView direction="horizontal">
      {rabbits.map((rabbit) => (
        <Rabbit
          key={rabbit.id}
          rabbit={rabbit}
          onSelect={(selectedRabbit) =>
            console.log('Selected rabbit:', selectedRabbit)
          }
        />
      ))}
    </SpatialNavigationView>
  </SpatialNavigationScrollView>
);

// Main component that renders multiple rows of rabbits
const Page = () => {

  return (
    <SpatialNavigationRoot>
      <SpatialNavigationScrollView>
        <RabbitRow />
        <RabbitRow />
        <RabbitRow />
        <RabbitRow />
        <RabbitRow />
        <RabbitRow />
      </SpatialNavigationScrollView>
    </SpatialNavigationRoot>
  );
};

const styles = StyleSheet.create({
  rabbit: {
    padding: 16,
    backgroundColor: '#f0f0f0',
    margin: 8,
    borderRadius: 8,
    width: 100,
    height: 200,
    justifyContent: 'center',
    alignItems: 'center',
  },
  rabbiFocused: {
    backgroundColor: '#e0e0e0',
  },
  rabbitText: {
    fontSize: 16,
    fontWeight: 'bold',
  },
});

export default Page;

Package.json:

{ "name": "AmazingKids", "version": "0.0.1", "private": true, "scripts": { "android": "expo run:android", "ios": "expo run:ios", "tvos": "expo run:ios --scheme AmazingKids-tvOS --device \"ATVHD\"", "lint": "eslint .", "start": "expo start", "test": "jest" }, "dependencies": { "expo": "^50.0.2", "mitt": "^3.0.1", "react": "18.2.0", "react-native": "npm:react-native-tvos@0.73.6-2", "react-tv-space-navigation": "^3.4.0" }, "devDependencies": { "@babel/core": "^7.20.0", "@babel/preset-env": "^7.20.0", "@babel/runtime": "^7.20.0", "@react-native/babel-preset": "0.73.21", "@react-native/eslint-config": "0.73.2", "@react-native/metro-config": "0.73.5", "@react-native/typescript-config": "0.73.1", "@types/react": "^18.2.6", "@types/react-test-renderer": "^18.0.0", "babel-jest": "^29.6.3", "eslint": "^8.19.0", "jest": "^29.6.3", "prettier": "2.8.8", "react-test-renderer": "18.2.0", "typescript": "5.0.4" }, "engines": { "node": ">=18" } }

And here's the error stack trace: Copy codeERROR TypeError: constructor is not callable

This error is located at: in SpatialNavigationRoot (created by Page) in Page (created by App) in App ... in SpaceNav(RootComponent), js engine: hermes

pierpo commented 7 months ago

Hi!

I tried to understand what could go wrong, but I don't know what. Does the example project in this repo work for you? Can you investigate the difference?

Thanks!

jvjijith commented 7 months ago

Nope Actually Got the Same Error

jijithjv commented 7 months ago

Hi! @pierpo ,

Thanks for replying, Tried running the example project ,but got the same error

pierpo commented 7 months ago

Hey, I just tried on tvOS on the example project and it does work fine for me. Do you reproduce only on tvOS? Have you tried web and android?