NK028
NK028

Reputation: 49

Invariant Violation : Invalid Hooks Call. Hooks Call can only be made inside body of function components

Hi am getting this error at Connect() function in LoginScreen.js. On commenting it its working fine. I am guessing either my Store is not properly setup or i am not able to connect LoginScreen Component to Redux Store.

LoginScreen.js

import React, { Component } from "react";
import PhoneInput from "react-native-phone-input";
import { connect } from "react-redux";
import { View, StatusBar } from "react-native";
import { Container, Item, Input, Button, Text } from "native-base";
import {
  phoneChanged,
  codeChanged,
  onCodeDispatched,
  onPhoneLogin,
  clearAuth,
  onSignOut
} from "../Actions/AuthActions";
//import firebase from "react-native-firebase";
import { auth } from "../Config/firebase";

export class LoginScreen extends Component {
}

export default connect(
  null, // passing null just for testing
  null
)(LoginScreen);

Store.js

import ReduxThunk from "redux-thunk";
import { createStore, applyMiddleware, compose } from "redux";
import reducer from "../Reducers/index";

let composeEnhancers = compose;
/*  eslint no-undef: 0    */
if (__DEV__) {
  /*  eslint no-underscore-dangle: 0    */
  composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
}

const store = createStore(
  reducer,
  {},
  composeEnhancers(applyMiddleware(ReduxThunk))
);

export { store };

AuthReducer.js

import {
  LOGIN_FAIL,
  LOGIN_SUCCESS,
  LOGIN_USER,
  PHONE_CHANGED,
  CODE_SENT_ERROR,
  CODE_CHANGED,
  CODE_DISPATCHED,
  LOGIN_USER_PHONE,
  CODE_SENT,
  CODE_NOT_CONFIRMED,
  LOGOUT,
  SET_USER_OBJECT,
  CLEAR_AUTH
} from "../Actions/ActionTypes";

const INITIAL_STATE = {
  phone: "+30",
  user: null,
  message: "",
  loading: false,
  codeInput: "",
  confirmResult: null
};

const AuthReducer = (state = INITIAL_STATE, action) => {
  console.log(action);

  switch (action.type) {
    case PHONE_CHANGED:
      return {
        ...state,
        phone: action.payload
      };
    case CODE_CHANGED:
      return {
        ...state,
        codeInput: action.payload
      };
    case LOGIN_USER:
      return {
        ...state,
        loading: true,
        message: ""
      };
    case LOGIN_USER_PHONE:
      return {
        ...state,
        loading: true,
        message: "Sending code...",
        phone: action.payload
      };
    case CODE_DISPATCHED:
      return {
        ...state,
        loading: true,
        message: ""
      };
    case CODE_SENT:
      return {
        ...state,
        loading: true,
        message: "Code has been sent!",
        confirmResult: action.payload
      };
    case CODE_SENT_ERROR:
      return {
        ...state,
        loading: false,
        message: `Sign in with Phone number error: ${action.payload}`,
        confirmResult: null
      };
    case SET_USER_OBJECT:
      return {
        ...state,
        user: action.payload
      };
    case CODE_NOT_CONFIRMED:
      return {
        ...state,
        message: `Code confirmation error: ${action.payload}`
      };
    case LOGIN_SUCCESS:
      return {
        ...INITIAL_STATE,
        user: action.payload,
        message: "login Success"
      };
    case LOGIN_FAIL:
      return {
        ...state,
        message: "Authentication Failed.",
        loading: false,
        password: "",
        phone: "+91"
      };
    case LOGOUT:
      return {
        ...state,
        message: "",
        user: null
      };
    case CLEAR_AUTH:
      return {
        ...state,
        ...INITIAL_STATE
      };
    default:
      return state;
  }
};

export default AuthReducer;

Root.js

import React from "react";
import { Provider } from "react-redux";
import { Navigator } from "./Navigation/Index";
import { store } from "./Store/Index";

export default class Root extends React.Component {
  render() {
    return (
      <Provider store={store}>
        <Navigator />
      </Provider>
    );
  }
}

AuthActions.js

//import { firebase } from "react-native-firebase";
import * as actionTypes from "./ActionTypes";
import { auth } from "../Config/firebase";

const phoneChanged = text => {
  return {
    type: actionTypes.PHONE_CHANGED,
    payload: text
  };
};

const onLoginSuccess = (dispatch, user) => {
  dispatch({
    type: actionTypes.LOGIN_SUCCESS,
    payload: user
  });
};

const signOut = dispatch => {
  dispatch({
    type: actionTypes.LOGOUT
  });
};

const onPhoneLogin = phone => {
  return dispatch => {
    dispatch({
      type: actionTypes.LOGIN_USER_PHONE
    });
    auth
      .signInWithPhoneNumber(phone)
      //  sign in success
      .then(confirmResult => {
        onCodeSent(dispatch, confirmResult);
      })
      //  sign in error
      .catch(error => onCodeSentError(dispatch, error));
  };
};

const codeChanged = text => {
  return {
    type: actionTypes.CODE_CHANGED,
    payload: text
  };
};

const onCodeSent = (dispatch, confirmResult) => {
  dispatch({
    type: actionTypes.CODE_SENT,
    payload: confirmResult
  });
};

const onCodeConfirmError = (dispatch, error) => {
  dispatch({
    type: actionTypes.CODE_NOT_CONFIRMED,
    payload: error
  });
};

const onCodeDispatched = code => {
  return (dispatch, getState) => {
    getState()
      .auth.confirmResult.confirm(code)
      .then(user => onLoginSuccess(dispatch, user))
      .catch(error => onCodeConfirmError(dispatch, error));
  };
};

const onCodeSentError = (dispatch, error) => {
  dispatch({
    type: actionTypes.CODE_SENT_ERROR,
    payload: error
  });
};

const onSignOut = () => {
  return dispatch => {
    auth
      .signOut()
      .then(() => signOut(dispatch))
      .catch(error => console.log(error));
  };
};

const clearAuth = () => {
  return dispatch => {
    dispatch({
      type: actionTypes.CLEAR_AUTH
    });
  };
};

export {
  onSignOut,
  clearAuth,
  codeChanged,
  onPhoneLogin,
  phoneChanged,
  onCodeDispatched
};

The Idea is basically to call LoginScreen which is part of 'Auth' StackNavigator and Render PhoneNumberInput and OTP.

Upvotes: 0

Views: 1067

Answers (1)

Muhammad Mehar
Muhammad Mehar

Reputation: 1055

React-redux (> 7.0.1) uses hook & React-native (< 0.59) doesn’t support Hooks yet.

You can run npm ls react-native in your application folder to check which version you’re using.

If you find more than one of them, this might also create problems. more on it

There are two solution

Upgrade the react native version to 0.59.0

OR

Downgrade the react redux version to 6.0.1

I hope it help you.

Upvotes: 1

Related Questions