在执行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
}
不应该抛出错误,道具应该能够访问状态属性。
答案 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))
);