typeError: null is not an object while accessing the Native Module
Asked Answered
K

5

6

I am working on one React Native Application and trying to access the Native Module from the android. I am following this official documentation enter link description here

After creating the Native Module, when I try to access it in the javaScript class, it shows the error that "typeError: null is not an object (Evaluating _ToastExample.default.show)"

ToastModule.java

package com.awesomeproject;

import android.widget.Toast;

import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

import java.util.Map;
import java.util.HashMap;

public class ToastModule extends ReactContextBaseJavaModule {
  private static ReactApplicationContext reactContext;

  private static final String DURATION_SHORT_KEY = "SHORT";
  private static final String DURATION_LONG_KEY = "LONG";

  ToastModule(ReactApplicationContext context) {
    super(context);
    reactContext = context;
  }

  @Override
  public String getName() {
    return "ToastExample";
  }

  @Override
  public Map<String, Object> getConstants() {
    final Map<String, Object> constants = new HashMap<>();
    constants.put(DURATION_SHORT_KEY, Toast.LENGTH_SHORT);
    constants.put(DURATION_LONG_KEY, Toast.LENGTH_LONG);
    return constants;
  }

  @ReactMethod
  public void show(String message, int duration) {
    Toast.makeText(getReactApplicationContext(), message, duration).show();
  }
}

CustomToastPackage.java

package com.awesomeproject;

import com.facebook.react.ReactPackage;
import com.facebook.react.bridge.NativeModule;
import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.uimanager.ViewManager;

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;

public class CustomToastPackage implements ReactPackage {

  @Override
  public List<ViewManager> createViewManagers(ReactApplicationContext reactContext) {
    return Collections.emptyList();
  }

  @Override
  public List<NativeModule> createNativeModules(
                              ReactApplicationContext reactContext) {
    List<NativeModule> modules = new ArrayList<>();

    modules.add(new ToastModule(reactContext));

    return modules;
  }

}

Inserted this snippet in MainApplication.java

 protected List<ReactPackage> getPackages() {
    @SuppressWarnings("UnnecessaryLocalVariable")
    List<ReactPackage> packages = new PackageList(this).getPackages();
    // Packages that cannot be autolinked yet can be added manually here, for example:
    // packages.add(new MyReactNativePackage());
    packages.add(new CustomToastPackage()); // <-- Add this line with your package name.
    return packages;
  }

ToastExample.js

import {NativeModules} from 'react-native';
module.exports = NativeModules.ToastExample;

App.js Here I am just trying to call that simple Toast function from Android Native Module.

import React, { Component } from 'react';
import EmojiDict from './components/EmojiDict';
import ToastExample from './ToastExample';

export default class App extends Component {

  componentDidMount(){
    ToastExample.show('Awesome', ToastExample.SHORT);
  }

  render() {
        return <
            EmojiDict />;
    }
}

Attaching error screenshot as well. enter image description here

I am new into ReactNative, so kindly help me figure out this issue. Thanks in advance.

Kathiekathleen answered 30/1, 2020 at 21:3 Comment(2)
Have you found the solution, mate?Spoilt
What I remember, that was my path problem, I was not referencing the ToastExample correctly into my App.js file.Kathiekathleen
P
3

Mine is solved like this

2 important steps to modify the above file

1.modify the getName of ToastModule.java file

 @Override
  public String getName() {
    return "ToastModule";   // ToastExample to ToastModule
  }

2.modify ToastExample.js file

import {NativeModules} from 'react-native';

export default NativeModules.ToastModule;  // ToastExample to ToastModule

But I don’t know why, it’s embarrassing,good luck!

Ptisan answered 10/5, 2021 at 14:28 Comment(0)
H
1

I had the same problem, was killing me for over a day. While googling I came across the @Mudasir's comment above in the question. In my case, it was a path issue too, in my index.js file: I was calling the native module with a different name (Toast) But in the index.js file I declared as ToastModule: My index.js file:

import { NativeModules } from 'react-native';

const { ToastModule} = NativeModules;

export default ToastModule;

From the app.js I after I imported as:

import ToastModule from 'react-native-custom-toast-module';
Horseflesh answered 8/7, 2020 at 9:19 Comment(0)
B
1

The issue might be that you're mixing two different module names: ToastModule and ToastExample.

Including:

public String getName() {
  return "ToastExample";
}

I had the same issue and that getName() mismatch was the reason for it.

Bahuvrihi answered 27/1, 2021 at 0:41 Comment(0)
H
0

In MainApplication you can see the getPackages() method is already available inside the ReactNativeHost

You need to add that package inside the

private final ReactNativeHost mReactNativeHost = new ReactNativeHost(this) {
    @Override
    public boolean getUseDeveloperSupport() {
        return BuildConfig.DEBUG;
    }

    @Override
    protected List<ReactPackage> getPackages() {
        List<ReactPackage> packages = new PackageList(this).getPackages();
        packages.add(new ModuleRegistryAdapter(mModuleRegistryProvider));
        //here you need to add
        packages.add(new CustomToastPackage());
        return packages;
    }

    @Override
    protected String getJSMainModuleName() {
        return "index";
    }

    @Override
    protected @Nullable
    String getJSBundleFile() {
        if (BuildConfig.DEBUG) {
            return super.getJSBundleFile();
        } else {
            return UpdatesController.getInstance().getLaunchAssetFile();
        }
    }

    @Override
    protected @Nullable
    String getBundleAssetName() {
        if (BuildConfig.DEBUG) {
            return super.getBundleAssetName();
        } else {
            return UpdatesController.getInstance().getBundleAssetName();
        }
    }
};
Hush answered 28/4, 2020 at 7:14 Comment(0)
E
0

I did everything correctly but the problem was, I just using the code by just refreshing but we need to rebuild the app (re-run)

     react-native run-android

and not just that but also we have to re-run every time we make a little change in native android(java) code

Eggshell answered 25/1, 2021 at 12:55 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.