Я разрабатываю реактивное приложение с использованием избыточности. Это мой app.js
:
import 'react-native-gesture-handler';
import React from 'react';
import {Provider} from 'react-redux';
import AsyncStorage from '@react-native-community/async-storage';
import {DefaultTheme, Provider as PaperProvider} from 'react-native-paper';
import {NavigationContainer} from '@react-navigation/native';
import {createBottomTabNavigator} from '@react-navigation/bottom-tabs';
import Icon from 'react-native-vector-icons/Ionicons';
import AppHeader from './components/ui/AppHeader';
import Home from './views/Home';
import Login from './views/Login';
import MyCoupons from './views/MyCoupons';
import ShoppingCart from './views/ShoppingCart';
import Signup from './views/Signup';
import Intro from './views/Intro';
import reducers from './reducers/index';
import configureStore from './store';
export const store = configureStore(reducers);
const Tab = createBottomTabNavigator();
const App = () => {
let localStorageUser = null;
const getLocalStorageUser = async () => {
try {
localStorageUser = await AsyncStorage.getItem('user');
} catch (error) {
console.info(error);
}
};
const getInitialRouteName = () => {
switch(localStorageUser) {
case null: return 'Cuenta'
case '': return 'Cuenta'
default: return 'Home'
}
}
return (
<>
<AppHeader />
<Provider store = {store}>
<PaperProvider>
<NavigationContainer>
<Tab.Navigator
initialRouteName = {getInitialRouteName()}
screenOptions = {({route}) => ({
tabBarIcon: ({focused, color, size}) => {
let iconName;
if (route.name == 'Home') {
iconName = focused? 'home': 'home-outline';
} else if (route.name == 'Mis Cupones') {
iconName = focused? 'film': 'film-outline';
} else if (route.name == 'Carrito') {
iconName = focused? 'cart': 'cart-outline';
} else if (route.name == 'Cuenta') {
iconName = focused? 'person-circle': 'person-circle-outline';
}
return <Icon name = {iconName} color='blue' size = {25} />
}
})}
>
<Tab.Screen name='Home' component = {Home} />
<Tab.Screen name='Carrito' component = {ShoppingCart} />
<Tab.Screen name='Mis Cupones' component = {MyCoupons} />
<Tab.Screen name='Cuenta' component = {Login}/>
</Tab.Navigator>
</NavigationContainer>
</PaperProvider>
</Provider>
</>
);
};
export default App;
Это мой store/index.js
:
import {applyMiddleware, compose, createStore} from 'redux';
import reducers from '../reducers/index';
import {routerMiddleware} from 'connected-react-router';
import createSagaMiddleware from 'redux-saga';
import rootSaga from '../sagas/index';
import {Provider} from 'react-redux';
import AsyncStorage from '@react-native-community/async-storage';
const sagaMiddleware = createSagaMiddleware();
const middlewares = [sagaMiddleware];
const composeEnhancers = window.__REDUX_DEVTOOLS_EXTENSION_COMPOSE__ || compose;
export default function configureStore(initialState) {
const store = createStore(initialState,
composeEnhancers(applyMiddleware(...middlewares)));
sagaMiddleware.run(rootSaga);
if (module.hot) {
// Enable Webpack hot module replacement for reducers
module.hot.accept('../reducers/index', () => {
const nextRootReducer = require('../reducers/index');
store.replaceReducer(nextRootReducer);
});
}
return store;
}
Это мой reducers/index.js
:
import {combineReducers} from 'redux';
import Auth from './Auth';
export default () => combineReducers({
auth: Auth,
});
Это мой reducers/Auth.js
:
import {
GET_USER_SUCCESS,
LOGIN_SUCCESS,
SET_USER,
} from '../types';
const INIT_STATE = {
username: null,
token: null,
userInfo: null,
};
export default (state = INIT_STATE, action) => {
switch (action.type) {
case LOGIN_SUCCESS: {
return {
...state,
username: action.payload.username,
token: action.payload.token
}
}
case GET_USER_SUCCESS: {
return {
...state,
userInfo: Object.assign({}, action.payload.userInfo)
}
}
case SET_USER: {
return {
...state,
username: null,
token: null,
userInfo: null,
}
}
default:
return state
}
}
А это views/Login.js
, где я пытаюсь подключиться к магазину:
import React from 'react';
import {View, StyleSheet} from 'react-native';
import {Button, TextInput, Headline} from 'react-native-paper';
import globalStyles from '../styles/global';
import {connect} from 'react-redux';
import AsyncStorage from '@react-native-community/async-storage';
import {login} from '../actions/Auth';
class Login extends React.Component {
constructor (props) {
super();
this.state = {
email: '',
password: '',
loggedIn: false
};
}
render () {
const setLocalStorageUser = async (user) => {
try {
await AsyncStorage.setItem('user', user);
} catch (error) {
console.info(error);
}
};
const handleNewUserPress = () => {
navigation.navigate('Signup');
}
const handleLoginPress = async () => {
login(this.state.email, this.state.password);
navigation.navigate('Home');
}
const handleChangeEvent = (name, text) => {
this.setState({[name]: value});
}
return (
<View style = {globalStyles.container}>
<TextInput style = {styles.input} value = {this.state.email} label = "Email" onChangeText = {(text) => handleChangeEvent('email', text)} />
<TextInput style = {styles.input} value = {this.state.password} label = "Contraseña" onChangeText = {(text) => handleChangeEvent('password', text)} />
<Button
style = {styles.button}
mode='contained'
onPress = {() => handleLoginPress()}
disabled = {this.state.email=='' || this.state.password==''}
>
Enviar
</Button>
<Button color='blue' icon = "plus-circle" onPress = {() => handleNewUserPress()}>
Nuevo Usuario
</Button>
</View>
);
}
}
const styles = StyleSheet.create({
input: {
marginBottom: 20,
backgroundColor: 'darkgray'
},
button: {
color: 'white',
backgroundColor: 'blue',
marginBottom: 20
}
})
const mapStateToProps = ({auth}) => {
const {username, token} = auth;
return {username, token};
}
const mapDispatchToProps = {
login,
}
export default connect(mapStateToProps, mapDispatchToProps)(Login);
Проблема в том, что эта аранжировка вызывает это исключение:
Я проверил код несколько раз, и я не смог найти свою ошибку.
Ваша проблема здесь:
export default () => combineReducers({
auth: Auth,
});
теперь ваш reducers
, который вы поставляете createStore
, является function
... не комбинированным редуктором
Это должно быть
export default combineReducers({
auth: Auth,
});