abpframework / abp

Open-source web application framework for ASP.NET Core! Offers an opinionated architecture to build enterprise software solutions with best practices on top of the .NET. Provides the fundamental infrastructure, cross-cutting-concern implementations, startup templates, application modules, UI themes, tooling and documentation.
https://abp.io
GNU Lesser General Public License v3.0
12.84k stars 3.43k forks source link

Unhandled Promise Rejection in React Mobile Framework #7602

Closed MDbrosev closed 3 years ago

MDbrosev commented 3 years ago

Steps to replicate from scratch:

  1. Create an ABP project; MVC; Entity Framework Core
  2. Set connection string and Migrate the DB
  3. Set appsettings.json to "SelfUrl" and "Authority" to my IP with http
  4. Set launchSettings.json - (There is no .HttpApi.Host/Properties but was found under .Web/Properties) to "applicationUrl" and "Authority" to IP with http
  5. Start .Web project
  6. Log in to web app - (Was able to log in successfully)
  7. Create user and log in to test if DB will update - (Created users successfully)
  8. Set up Conveyor to get exposed IP address for react front end for testing
  9. Ran Yarn to init react project
  10. Opened react project and added the http remote URL from Conveyor to Environment.js - (Making sure that issuer and apiUrl matches the running address of the .Web project.)
  11. Ran Yarn start
  12. Open Expo on iOS and open project
  13. Log in with Admin or User credentials - (Causes error below)

Results in the following error:

[Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'delete state.activeLoadings[action.payload.key]')]
* src\store\reducers\LoadingReducer.js:17:34 in builder.addCase.addCase$argument_1
- node_modules\immer\dist\immer.esm.js:1:16047 in i.produce
* [native code]:null in <unknown>
* [native code]:null in reduce
- node_modules\redux\lib\redux.js:464:32 in combination
- node_modules\redux-persist\lib\persistReducer.js:156:26 in <anonymous>
- node_modules\redux\lib\redux.js:218:6 in dispatch
* http://10.0.0.191:19001/node_modules%5Cexpo%5CAppEntry.bundle?platform=ios&dev=true&hot=false&minify=false:207400:27 in <unknown>
* src\screens\Login\LoginScreen.js:57:15 in login.then.then._finally$argument_0
- node_modules\react-native\node_modules\promise\setimmediate\finally.js:12:28 in then$argument_1
- node_modules\react-native\node_modules\promise\setimmediate\core.js:37:13 in tryCallOne
- node_modules\react-native\node_modules\promise\setimmediate\core.js:123:24 in setImmediate$argument_0
- node_modules\react-native\Libraries\Core\Timers\JSTimers.js:130:14 in _callTimer
- node_modules\react-native\Libraries\Core\Timers\JSTimers.js:181:14 in _callImmediatesPass
- node_modules\react-native\Libraries\Core\Timers\JSTimers.js:441:30 in callImmediates
- node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:387:6 in __callImmediates
- node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:135:6 in __guard$argument_0
- node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:364:10 in __guard
- node_modules\react-native\Libraries\BatchedBridge\MessageQueue.js:134:4 in flushedQueue
* [native code]:null in flushedQueue
* [native code]:null in callFunctionReturnFlushedQueue

Code:

import { createReducer } from '@reduxjs/toolkit';
import LoadingActions from '../actions/LoadingActions';

const initialState = { activeLoadings: {}, loading: false };

export default createReducer(initialState, builder =>
  builder
    .addCase(LoadingActions.start, (state, action) => {
      const { key, opacity } = action.payload;
      return {
        ...state,
        actives: { ...state.activeLoadings, [key]: action },
        loading: true,
        opacity,
      };
    })
    .addCase(LoadingActions.stop, (state, action) => {
      delete state.activeLoadings[action.payload.key];

      state.loading = !!Object.keys(state.activeLoadings).length;
    })
    .addCase(LoadingActions.clear, () => ({})),
);
MDbrosev commented 3 years ago

As per the documentation - "Make sure that issuer and apiUrl matches the running address of the .HttpApi.Host or .Web project." When using Conveyor the local and remote ports do not match, could this be the issue?

mehmet-erim commented 3 years ago

Hi @MDbrosev

I reproduced it without Conveyor and I see the error you mentioned:

[Unhandled promise rejection: TypeError: undefined is not an object (evaluating 'delete state.activeLoadings[action.payload.key]')]

However, it is not a blocker for the app. If you refresh the running app in the Expo, the error does not occur again. I configured the backend to run on my IP address with HTTP, I could not see any problem. Your problem is probably related to the Conveyor.

If you solve the problem, please let us know the solution.

I created an issue about the TypeError above: https://github.com/abpframework/abp/issues/7646

stale[bot] commented 3 years ago

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

mugambiwarwema commented 3 years ago

@MDbrosev @mehmet-erim

I have reproduced the issue on abp v4.3.

I am unable to login to the react-native app after configuring the app (backend and react-frontend) as stated in the official abp-react-native Getting Started guide.

If you solved the issue kindly advise how you handled it.

Thank you in abdance.

ShifanilaSenthil commented 9 months ago

If you solved the issue kindly advise how you handled it.

Thank you in advance.

MDbrosev commented 9 months ago

@ShifanilaSenthil @mugambiwarwema If I remember correctly, the RN app in Expo blocks HTTP requests. I deployed the backend which provided me with an HTTPS URL and was able to work around it.

ShifanilaSenthil commented 9 months ago

@mugambiwarwema I have given the running address of authserver as apiurl and running address of HttpApi.Host as Issuer in Env.js file, i am trying to run as emulator not from an Expo app..but still this error occurs.

MDbrosev commented 9 months ago

@ShifanilaSenthil Take a look at the RN networking docs; it's actually iOS and Android blocking the request since it is not HTTPS. Have you tried replacing localhost in the api url with the ipv4 address of the machine running the service?

https://reactnative.dev/docs/network

By default, iOS 9.0 or later enforce App Transport Security (ATS). ATS requires any HTTP connection to use HTTPS. If you need to fetch from a clear text URL (one that begins with http) you will first need to add an ATS exception. If you know ahead of time what domains you will need access to, it is more secure to add exceptions only for those domains; if the domains are not known until runtime you can disable ATS completely.

On Android, as of API Level 28, clear text traffic is also blocked by default. This behavior can be overridden by setting "android:usesCleartextTraffic" in the app manifest file.

jegank commented 9 months ago

@MDbrosev , The issue still exist even after enabling the "usesCleartextTraffic": true in the app.json file.

"plugins": [ [ "expo-build-properties", { "android": { "usesCleartextTraffic": true }, "ios": { "deploymentTarget": "13.0", "usesCleartextTraffic": true } } ] ]

The APIs and AuthServer are running in HTTP, and given my localIP instead of the localhost, but the issue is not yet resolved. This issue seems happening always if we follow the documentation. Can you please help on this asap as it is blocking my development?