react-native-toolbar-android / toolbar-android

MIT License
48 stars 36 forks source link

Error in render method of of ToolbarAndroidNative in toolbar-android v 0.2.1 #101

Open vladp opened 10 months ago

vladp commented 10 months ago

Error on line 230, column 24 in ToolbarAndroid.android.js (see screenshot for error message) '.. requireNativeComponent is not a function it is an object'

package.json


  "devDependencies": {
    "@babel/core": "^7.20",
    "@babel/preset-flow": "^7",
    "flow-bin": "^0.221",
    "flow-typed": "^3.9",
    "npm-run-all": "^4",

    "@types/react": "~18.2.14",
    "typescript": "^5.1.3"

  },
  "dependencies": {
    "expo": "~50.0.0-alpha.6",
    "expo-status-bar": "~1.9.0",
    "react": "18.2.0",
    "react-native": "0.72.5",
    "@react-native-community/checkbox": "^0",
    "@react-native-community/slider": "^4",
    "@react-native-community/toolbar-android": "^0.2",
    "@react-native-picker/picker": "^2",
    "@types/react": "~18.0.27",
    "expo-av": "^13",
    "expo-splash-screen": "~0.24.0",
    "js-search": "^2",
    "prop-types": "^15",
    "pubsub-js": "^1",
    "react-native-markdown-display": "^6",
    "react-native-modal": "^13",
    "react-native-vector-icons": "^10",
    "react-router-native": "^6.3",
    "tree-model": "^1",
    "unmutable": "^0"
  },
  "expo": {
    "autolinking": {
      "android": {
        "exclude": [
          "@expo/vector-icons",
          "react-native-webview"
        ]
      },
      "ios": {
        "exclude": [
          "@expo/vector-icons",
          "expo-keep-awake",
          "expo-font"
        ]
      }
    }
  }

Activity invoking the React native (using autolinking, and I confirmed that com.reactnativecommunity.toolbarandroid.ReactToolbarPackage; is included in the array of packages (List packages ).

        mReactRootView = new ReactRootView(this);
        List<ReactPackage> packages = new PackageList(getApplication()).getPackages();

        mReactInstanceManager = ReactInstanceManager.builder()
                .setApplication(getApplication())
                .setCurrentActivity(this)
                .setBundleAssetName("index.android.bundle")
                .setJSMainModulePath("index")  
                .addPackages(packages) //adding autloinked packages
                .addPackage(new SurveyMgrReactPackage())

                .setUseDeveloperSupport(BuildConfig.DEBUG)
                .setInitialLifecycleState(LifecycleState.RESUMED)
                .build();

Class where I use the tool bar:


import isEqual from 'lodash/isEqual';
import pick from 'lodash/pick';

import React, {Component} from 'react';
import { Text } from 'react-native';

import PropTypes from 'prop-types';
import {Icon} from '../../mdk/RNVI';

import type { Node } from 'react';

import ToolbarAndroid from '@react-native-community/toolbar-android';

const ICON_PROP_NAMES = ['iconSize', 'iconColor', 'titleColor'];
const LOGO_ICON_PROP_NAMES = [...ICON_PROP_NAMES, 'logoName'];
const NAV_ICON_PROP_NAMES = [...ICON_PROP_NAMES, 'navIconName'];
const OVERFLOW_ICON_PROP_NAMES = [...ICON_PROP_NAMES, 'overflowIconName'];
const ACTIONS_PROP_NAMES = [...ICON_PROP_NAMES, 'actions'];

const arePropsEqual = (keys) => (prevProps, nextProps) =>
  isEqual(pick(prevProps, keys), pick(nextProps, keys));

const areLogoIconPropsEqual = arePropsEqual(LOGO_ICON_PROP_NAMES);
const areNavIconPropsEqual = arePropsEqual(NAV_ICON_PROP_NAMES);
const areOverflowIconPropsEqual = arePropsEqual(OVERFLOW_ICON_PROP_NAMES);
const areActionPropsEqual = arePropsEqual(ACTIONS_PROP_NAMES);

const IconNamePropType = PropTypes.oneOf(Object.keys(Icon.getRawGlyphMap()));

let getImageSource = Icon.getImageSource;

export class LCSIconToolbarShim extends React.PureComponent {
  static defaultProps = {
    iconSize: 24,
  };

  static propTypes = {
    logoName: IconNamePropType,
    navIconName: IconNamePropType,
    overflowIconName: IconNamePropType,
    actions: PropTypes.arrayOf(
      PropTypes.shape({
        title: PropTypes.string.isRequired,
        iconName: IconNamePropType,
        iconSize: PropTypes.number,
        iconColor: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
        show: PropTypes.oneOf(['always', 'ifRoom', 'never']),
        showWithText: PropTypes.bool,
      }),
    ),
    iconSize: PropTypes.number,
    iconColor: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
    titleColor: PropTypes.oneOfType([PropTypes.string, PropTypes.number]),
  };

  constructor(props) {
    super(props);

    this.state = {
      logo: undefined,
      navIcon: undefined,
      overflowIcon: undefined,
      actions: undefined,
    };
  } /* end of constructor */

  componentDidMount() {
    this.updateLogoIconSource();
    this.updateNavIconSource();
    this.updateOverflowIconSource();
    this.updateActionIconSources();
  }

  componentDidUpdate(prevProps) {
    if (!areLogoIconPropsEqual(prevProps, this.props)) {
      this.updateLogoIconSource();
    }
    if (!areNavIconPropsEqual(prevProps, this.props)) {
      this.updateNavIconSource();
    }
    if (!areOverflowIconPropsEqual(prevProps, this.props)) {
      this.updateOverflowIconSource();
    }
    if (!areActionPropsEqual(prevProps, this.props)) {
      this.updateActionIconSources();
    }
  }

  async updateLogoIconSource() {
    const {logoName, iconSize, iconColor, titleColor} = this.props;
    if (logoName) {
      const logo = await getImageSource(
        logoName,
        iconSize,
        iconColor || titleColor,
      );
      this.setState({logo});
      // eslint-disable-next-line react/destructuring-assignment
    } else if (this.state.logo) {
      this.setState({logo: undefined});
    }
  }

  async updateNavIconSource() {
    const {navIconName, iconSize, iconColor, titleColor} = this.props;
    if (navIconName) {
      const navIcon = await getImageSource(
        navIconName,
        iconSize,
        iconColor || titleColor,
      );
      this.setState({navIcon});
      // eslint-disable-next-line react/destructuring-assignment
    } else if (this.state.navIcon) {
      this.setState({navIcon: undefined});
    }
  }

  async updateOverflowIconSource() {
    const {overflowIconName, iconSize, iconColor, titleColor} = this.props;
    if (overflowIconName) {
      const overflowIcon = await getImageSource(
        overflowIconName,
        iconSize,
        iconColor || titleColor,
      );
      this.setState({overflowIcon});
      // eslint-disable-next-line react/destructuring-assignment
    } else if (this.state.overflowIcon) {
      this.setState({overflowIcon: undefined});
    }
  }

  async updateActionIconSources() {
    const {actions, iconSize, iconColor, titleColor} = this.props;
    const updatedActions = await Promise.all(
      (actions || []).map((action) => {
        if (action.iconName) {
          return getImageSource(
            action.iconName,
            action.iconSize || iconSize,
            action.iconColor || iconColor || titleColor,
          ).then((icon) => ({...action, icon}));
        }
        return Promise.resolve(action);
      }),
    );
    this.setState({actions: updatedActions});
  }

  render(): Node {
    return <ToolbarAndroid {...this.props} {...this.state} />;
  }
} /*end of LCSIconToolbarShim class */

I am using Hermes java script engine. More info on the enviroment

> react-native info

info Fetching system and libraries information...
System:
  OS: Linux 5.15 Manjaro Linux
  CPU: (6) x64 12th Gen Intel(R) Core(TM) i7-12700H
  Memory: 1.15 GB / 15.28 GB
  Shell:
    version: 5.2.15
    path: /bin/bash
Binaries:
  Node:
    version: 18.16.0
    path: ~/.nvm/versions/node/v18.16.0/bin/node
  Yarn:
    version: 1.22.19
    path: ~/.nvm/versions/node/v18.16.0/bin/yarn
  npm:
    version: 9.5.1
    path: ~/.nvm/versions/node/v18.16.0/bin/npm
  Watchman: Not Found
SDKs:
  Android SDK: Not Found
IDEs:
  Android Studio: Not Found
Languages:
  Java:
    version: 11.0.21
    path: /sbin/javac
  Ruby:
    version: 3.0.6
    path: /sbin/ruby
npmPackages:
  "@react-native-community/cli": Not Found
  react:
    installed: 18.2.0
    wanted: 18.2.0
  react-native:
    installed: 0.72.5
    wanted: 0.72.5
npmGlobalPackages:
  "*react-native*": Not Found
Android:
  hermesEnabled: true
  newArchEnabled: false
iOS:
  hermesEnabled: Not found
  newArchEnabled: Not found

See screen shot for the error location

Screenshot_AndroidToolBar-problem

vanHoi commented 10 months ago

Same problem here. When we downgrade to React Native 0.71 it works fine, but after upgrading to 0.72 ToolbarAndroid becomes broken.

vladp commented 10 months ago

@vanHoi thank you for the confirmation. I cannot move back to prev react-native version, unfortunately. I had just completed a bunch of upgrades related to Expo (another big dependency I have, and when I changed back to prev react version, due to Expo changes, I could not even build with 0.71x). @EvanBacon is there a chance that this module would be made compatible with React native 0.72x >

ieatfood commented 7 months ago

I used patch-package with this diff to get it to work on React Native 0.72:

diff --git a/node_modules/@react-native-community/toolbar-android/js/ToolbarAndroidNativeComponent.js b/node_modules/@react-native-community/toolbar-android/js/ToolbarAndroidNativeComponent.js
index 07f9e20..cc51d1c 100644
--- a/node_modules/@react-native-community/toolbar-android/js/ToolbarAndroidNativeComponent.js
+++ b/node_modules/@react-native-community/toolbar-android/js/ToolbarAndroidNativeComponent.js
@@ -10,7 +10,7 @@

 'use strict';

-const requireNativeComponent = require('react-native/Libraries/ReactNative/requireNativeComponent');
+const {requireNativeComponent} = require('react-native');

 import type {SyntheticEvent} from 'react-native/Libraries/Types/CoreEventTypes';
 import type {ImageSource} from 'react-native/Libraries/Image/ImageSource';

I don't know if this is backwards compatible with older versions otherwise I'd submit a PR.

vladp commented 6 months ago

@ieatfood your one line fix in this component -- fixed the issue! How did you figure this out, if I may ask? Was there an API change announcement on react-native side that indicated that this change is needed?

I would certainly submit PR because as of now this component is not working with recent version of react native. May be the maintainers @EvanBacon @vanHoi will create appropriate version for this update, that does not impact react-native users of the pre 0.72 releases.