未定义不是对象(评估auth.confirmResult)

时间:2019-05-18 18:32:28

标签: reactjs react-native react-redux

在执行MapsStatetoProps和connect()之后,尝试通过渲染功能中的道具访问状态属性“ confirmResult”时,在LoginScreen.js组件中出现错误。

Screens \ LoginScreen.js

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

export class LoginScreen extends Component {
  static navigationOptions = {
    header: null
  };

  constructor(props) {
    super(props);
    this.state = {
      valid: ""
    };
  }

  componentDidMount() {
    this.unsubscribe = firebaseAuth.onAuthStateChanged(user => {
      if (user) {
        this.props.navigation.navigate("App");
      }
    });
  }

  componentWillUnmount() {
    if (this.unsubscribe) this.unsubscribe();
  }

  render() {
    const { auth } = this.props;
    return (
      <Container style={{ flex: 1, backgroundColor: "#4F6D7A" }}>
        <StatusBar barStyle="light-content" backgroundColor="#062b40" />
        <Text>This is LoginScreen</Text>
        <Container
          style={{
            flex: 1,
            justifyContent: "center",
            backgroundColor: "#4F6D7A"
          }}
        >
          {auth.confirmResult}
        </Container>
      </Container>
    );
  }
}

const mapStateToProps = state => {
  console.log(JSON.stringify(state) + "*************");
  return {
    auth: state.auth
  };
};

export default connect(
  mapStateToProps,
  { phoneChanged }
)(LoginScreen);

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";

export const INITIAL_STATE = {
  phone: "+91",
  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
      };
    default:
      return state;
  }
};

export default AuthReducer;

Reducers \ index.js

import { combineReducers } from "redux";
import AuthReducer from "./AuthReducer";

export default combineReducers({
  auth: AuthReducer
});

Root.js

import React from "react";
import { Provider } from "react-redux";
import { Navigator } from "./Navigation/index";
import { store } from "./Store/index";
import LoginContainer from "./Screens/LoginScreen";

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

Store \ index.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 };

Actions \ 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
  };
};

export { phoneChanged };

Navigation \ index.js

import {
  createStackNavigator,
  createSwitchNavigator,
  createAppContainer
} from "react-navigation";
import AuthLoading from "../Screens/AuthLoading";
import HomeScreen from "../Screens/HomeScreen";
import { LoginScreen } from "../Screens/LoginScreen";

const AuthStack = createStackNavigator({
  Login: LoginScreen
});

const AppStack = createStackNavigator({
  Home: HomeScreen
});

const switchNavigator = createSwitchNavigator(
  {
    AuthLoading: AuthLoading,
    App: AppStack,
    Auth: AuthStack
  },
  {
    initialRouteName: "AuthLoading"
  }
);

export const Navigator = createAppContainer(switchNavigator);

package.json

{
  "scripts": {
    "start": "react-native start",
    "android": "react-native run-android",
    "ios": "react-native run-ios"
  },
  "dependencies": {
    "@babel/runtime": "^7.4.4",
    "firebase": "^5.11.1",
    "isomorphic-fetch": "^2.2.1",
    "native-base": "^2.12.1",
    "prop-types": "^15.7.2",
    "react": "^16.8.6",
    "react-native": "0.57.5",
    "react-native-firebase": "^5.3.1",
    "react-native-gesture-handler": "^1.1.0",
    "react-native-otp-inputs": "^2.0.1",
    "react-native-phone-input": "^0.2.1",
    "react-navigation": "^3.9.1",
    "react-redux": "^7.0.3",
    "redux": "^4.0.1",
    "redux-immutable-state-invariant": "^2.1.0",
    "redux-thunk": "^2.3.0"
  },
  "devDependencies": {
    "babel-polyfill": "^6.26.0",
    "babel-preset-expo": "^5.0.0",
    "eslint-plugin-react-hooks": "^1.6.0",
    "expo": "^32.0.6"
  },
  "private": true
}

不应该抛出错误,道具应该能够访问状态属性。

2 个答案:

答案 0 :(得分:0)

按如下所示修改构造函数:

constructor(props) {
    super(props)
    ........
}

按如下方式存储索引文件:

import reducer from "../Reducer/index"

根文件如下:

import { Navigator } from "./Navigation/index"

import { store } from "./Store/index"

导航/索引如下:

import LoginScreen from "../Screens/LoginScreen"

React-redux(> 7.0.1)使用钩子& React-native(<0.59)尚不支持Hooks。

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

如果您发现其中一个以上,则可能还会造成问题。 more on it

有两种解决方案

将react本机版本升级到0.59.0

OR

将React Redux版本降级到6.0.1

希望对您有帮助。

答案 1 :(得分:0)

关于createStore的第二个参数:

  

[preloadedState]( any ):初始状态。您可以选择指定它,以在通用应用程序中混合服务器中的状态,或还原以前序列化的用户会话。如果您使用CombineReducers制作了reducer,则该对象必须是形状与传递给它的键相同的普通对象。

因此{}会覆盖初始状态,不会像预期的那样成为{auth: ...} ...应该可以像compose示例中那样跳过参数,例如:

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