Redux 连接无法访问商店

时间:2020-12-19 06:26:20

标签: javascript react-native redux react-redux

我正在使用 redux 开发一个 react-native 应用程序。这是我的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.log(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.log(error);
      }
    };
  
    const handleNewUserPress = () => {
      navigation.navigate('Signup');
    }
  
    const handleLoginPress = async () => {
      login(this.state.email, this.state.password);
  
      navigation.navigate('Home');
    }

    const handleChange = (name, text) => {
      this.setState({[name]: value});
    }

    return (
      <View style={globalStyles.container}>
        <TextInput style={styles.input} value={this.state.email} label="Email" onChangeText={(text) => handleChange('email', text)} />
        <TextInput style={styles.input} value={this.state.password} label="Contraseña" onChangeText={(text) => handleChange('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);

问题是这种安排引发了这个异常:

enter image description here

我已经多次检查代码,但我一直无法找到我的错误。

1 个答案:

答案 0 :(得分:0)

您的问题在这里:

export default () => combineReducers({
  auth: Auth,
});

现在你提供给 reducerscreateStore 是一个 function ... 不是组合减速器

应该是

   export default combineReducers({
      auth: Auth,
    });