首页 > 解决方案 > 不变违规:无效的 Hooks 调用。Hooks 调用只能在函数组件内部进行

问题描述

您好,在 LoginScreen.js 的 Connect() 函数中出现此错误。在评论它工作正常。我猜我的商店没有正确设置,或者我无法将 LoginScreen 组件连接到 Redux 商店。

登录屏幕.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;

根.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
};

这个想法基本上是调用 LoginScreen,它是“Auth”StackNavigator 的一部分,并呈现 PhoneNumberInput 和 OTP。

标签: react-nativeredux

解决方案


React-redux (> 7.0.1) 使用 hook & React-native (< 0.59) 还不支持 Hooks。

您可以npm ls react-native在应用程序文件夹中运行以检查您使用的版本。

如果您发现其中不止一个,这也可能会产生问题。更多关于它

有两种解决方案

将 react 原生版本升级到 0.59.0

或者

将 react redux 版本降级到 6.0.1

我希望它对你有帮助。


推荐阅读