繁体   English   中英

TypeError:undefined不是函数(评估调度)

[英]TypeError: undefined is not a function (evaluating dispatch)

我试图将React Redux与React Native结合在一起,并且在调试程序时遇到了这个奇怪的错误:

TypeError: undefined is not a function (evaluating 'dispatch((0, _LoginActions.loginAction)(inputFormProp))')

运行该程序后,立即从组件的登录功能中触发了该错误,但我不知道为什么会有该错误。

这是我的组件代码:

import React, { Component } from 'react';
import { Text, View, TextInput, ActivityIndicator, TouchableHighlight } from 'react-native';
import { getLogger, issueToText } from '../core/utils';
import styles from '../core/styles';
import { Card, Button, FormLabel, FormInput } from "react-native-elements";
import { connect } from 'react-redux'
import { loginAction } from '../actions/LoginActions'

export class LoginComponent extends Component {
constructor(props) {
    super(props);
    this.login = this.login.bind(this)
}

render() {
    const { error, isLoading } = this.props;

    const inputFormProp = {
        username: '',
        password: ''
    };

    return (
        <View style={{ paddingVertical: 20 }}>
            <Card>
                <FormLabel>Email</FormLabel>
                <FormInput value={inputFormProp.username} onChangeText={(text) => inputFormProp.username = text} />
                <FormLabel>Password</FormLabel>
                <FormInput value={inputFormProp.password} onChangeText={(text) => inputFormProp.password = text} />

                <Button
                    buttonStyle={{ marginTop: 20 }}
                    backgroundColor="#03A9F4"
                    title="SIGN IN"
                    onPress={this.login(inputFormProp)}
                />
            </Card>
            <ActivityIndicator animating={this.props.isLoading} style={styles.activityIndicator} size="large" />
        </View>
    );
}


login(inputFormProp) {
    const { store } = this.props.screenProps.store;

    const { dispatch } = this.props

    dispatch(loginAction(inputFormProp))
        .then(() => {
            if (this.props.error === null && this.props.isLoading === false) {
                if (store.getState().auth.token) {
                    this.props.navigation.navigate('ProductList', { token: store.getState().auth.token });
                }
            }
        })
        .catch(error => {
        });
}


}

function mapStateToProps(state) {
const { error, isLoading } = state.auth

return {
    error,
    isLoading,
}
}

export default connect(mapStateToProps)(LoginComponent)

这是我的app.js代码:

const initialState = {
  auth: { isLoading: false, error: null },
};


const rootReducer = combineReducers({ product: productReducer, auth: authReducer 
});

const store = createStore(rootReducer, initialState, applyMiddleware(thunk, 
createLogger()));

export const MyNavigator = StackNavigator({
  Login: { screen: LoginComponent },
  ProductList: { screen: ProductList },
});



export default class App extends Component {
  render() {
    return (
      <MyNavigator screenProps={{ store: { store } }} />
    );
  }
};

从我已经搜索过的错误中看来,原因似乎是组件中的connect()函数,但我不知道它到底出了什么问题。

这是我的目录结构:

在此处输入图片说明

这是LoginActions文件:

import { loginService } from '../services/LoginService'

export function loginAction(data) {
    return dispatch => {
        loginService(data);
    }
}

这是LoginService文件:

import { httpApiUrl } from '../core/api';
import { getLogger } from "../core/utils";
import { Alert } from 'react-native';
const log = getLogger('auth/service');


export const loginService = (user) => (dispatch) => {
dispatch({ type: 'LOGIN_STARTED' });
return fetch(`${httpApiUrl}/api/userdata/verify`, {
    method: 'POST',
    headers: {
        'Accept': '*/*',
        'Content-Type': 'application/json',
    },
    body: JSON.stringify(user)
})
    .then((response) => {
        if (!response.ok) {
            Alert.alert('ERROR', 'User or password is incorrect');
            dispatch({ type: 'LOGIN_FAILED', data: 'User or password is incorrect' });
        }
        else return response;
    }).then((response) => response.json).then((response) => {
        dispatch({ type: 'LOGIN_SUCCEEDED', data: response.json });

    })
    .catch(error => {
        dispatch({ type: 'LOGIN_FAILED', data: error.message });
    });
};

这是this.props的输出

21:10:48: Object {
21:10:48:   "navigation": Object {
21:10:48:     "dispatch": [Function anonymous],
21:10:48:     "goBack": [Function goBack],
21:10:48:     "navigate": [Function navigate],
21:10:48:     "setParams": [Function setParams],
21:10:48:     "state": Object {
21:10:48:       "key": "Init-id-1515093047465-0",
21:10:48:       "routeName": "Login",
21:10:48:     },
21:10:48:   },
21:10:48:   "screenProps": Object {
21:10:48:     "store": Object {
21:10:48:       "store": Object {
21:10:48:         "@@observable": [Function observable],
21:10:48:         "dispatch": [Function anonymous],
21:10:48:         "getState": [Function getState],
21:10:48:         "replaceReducer": [Function replaceReducer],
21:10:48:         "subscribe": [Function subscribe],
21:10:48:       },
21:10:48:     },
21:10:48:   },
21:10:48: }

您需要在类声明之前删除带前缀的export关键字

class LoginComponent extends Component { //<--- export was present here 
constructor(props) {
    super(props);
    this.login = this.login.bind(this)
}

render() {
    const { error, isLoading } = this.props;

    const inputFormProp = {
        username: '',
        password: ''
    };

    return (
        <View style={{ paddingVertical: 20 }}>
            <Card>
                <FormLabel>Email</FormLabel>
                <FormInput value={inputFormProp.username} onChangeText={(text) => inputFormProp.username = text} />
                <FormLabel>Password</FormLabel>
                <FormInput value={inputFormProp.password} onChangeText={(text) => inputFormProp.password = text} />

                <Button
                    buttonStyle={{ marginTop: 20 }}
                    backgroundColor="#03A9F4"
                    title="SIGN IN"
                    onPress={this.login(inputFormProp)}
                />
            </Card>
            <ActivityIndicator animating={this.props.isLoading} style={styles.activityIndicator} size="large" />
        </View>
    );
}


login(inputFormProp) {
    const { store } = this.props.screenProps.store;

    const { dispatch } = this.props

    dispatch(loginAction(inputFormProp))
        .then(() => {
            if (this.props.error === null && this.props.isLoading === false) {
                if (store.getState().auth.token) {
                    this.props.navigation.navigate('ProductList', { token: store.getState().auth.token });
                }
            }
        })
        .catch(error => {
        });
}


}

function mapStateToProps(state) {
const { error, isLoading } = state.auth

return {
    error,
    isLoading,
}
}

export default connect(mapStateToProps)(LoginComponent)

还要确保您将LoginComponent导入为默认导入。

在我看来,由于babel设置或其他原因,导致模块导入混乱。 您可以在浏览器抱怨的行上设置一个断点,并在控制台中评估_LoginActions.loginAction 确保未定义。

比在范围内找到_LoginActions,问题将显而易见。 如果不是,那么请让我们知道相应范围的外观。 Scope是chrome dev工具调试器“来源”部分中的标签

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM