简体   繁体   English

为什么我收到无效值错误?

[英]Why am I getting an invalid value error?

I don't understand how I'm getting this error (pic below). 我不明白我是如何得到这个错误的(下图)。 In my LoginForm.js file, the onEmailChange(text) is giving me an unresolved function or method call to onEmailChange() error when I hover over it in my WebStorm IDE. 在我的LoginForm.js文件中,当我将鼠标悬停在我的WebStorm IDE中时, onEmailChange(text)给我一个unresolved function or method call to onEmailChange()错误。 In my index.js file, no error is being thrown anywhere. 在我的index.js文件中,没有任何错误被抛出。

I've looked around SO for this issue but it doesn't fully pertain to my problem. 我已经把这个问题环顾四周,但它并不完全与我的问题有关。

I've tried File > Invalidate Caches/Restart but that didn't work. 我已经尝试过File > Invalidate Caches/Restart但是没有用。

在此输入图像描述

Here's App.js : 这是App.js

import React, { Component } from 'react';
import {StyleSheet} from 'react-native';
import {Provider} from 'react-redux';
import {createStore} from 'redux';
import firebase from 'firebase';
import reducers from './reducers';
import LoginForm from './components/common/LoginForm';

class App extends Component {
    render() {
        return(
            <Provider style={styles.c} store={createStore(reducers)}>
                <LoginForm/>
            </Provider>
        );
    }
}

const styles = StyleSheet.create({
    c: {
        flex: 1
    }
});


export default App;

Here's LoginForm.js : 这是LoginForm.js

import React, {Component} from 'react';
import {connect} from 'react-redux';
import {emailChanged} from 'TorusTeensApp/src/actions';
import {Text, StyleSheet, KeyboardAvoidingView, TextInput, TouchableOpacity} from 'react-native';

class LoginForm extends Component {
    render() {
        onEmailChange(text)
        {
            this.props.emailChanged(text);
        }

        return(
            <KeyboardAvoidingView style={styles.container}>
                <TextInput
                    style={styles.userInput}
                    onsubmitediting={() => this.passwordInput.focus()}
                    returnKeyType={"next"}
                    placeholder={"Email"}
                    label={"Email"}
                    keyboardType={"email-address"}
                    autoCorrect={false}
                    onChangeText={this.onEmailChange.bind(this)}
                    value={this.props.email}
                />

                <TextInput
                    style={styles.userInput}
                    ref={(userInput) => this.passwordInput = userInput}
                    returnKeyType={"go"}
                    placeholder={"Password"}
                    label={"Password"}
                    secureTextEntry
                />

                <TouchableOpacity style={styles.buttonContainer}>
                    <Text style={styles.buttonText}>Login</Text>
                </TouchableOpacity>

                <TouchableOpacity style={styles.buttonContainer}>
                    <Text style={styles.buttonText}>Create Account</Text>
                </TouchableOpacity>
            </KeyboardAvoidingView>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        padding: 20 // creates a gap from the bottom
    },

    userInput: {
        marginBottom: 20,
        backgroundColor: '#9b42f4',
        height: 40
    },

    buttonContainer: {
        backgroundColor: '#41bbf4',
        paddingVertical: 10,
        marginBottom: 20
    },

    buttonText: {
        textAlign: 'center',
        color: '#FFFFFF'
    }
});

const mapStateToProps = state =>  {
  return {
      email: state.auth.email
  };
};
export default connect(mapStateToProps, null, {emailChanged}) (LoginForm);

Here's index.js : 这是index.js

import {EMAIL_CHANGED} from './types';

export const emailChanged = (text) => {
    return {
        type: 'EMAIL_CHANGED',
        payload: text
    };
};

export default emailChanged();

You defined your callback inside your render() method and not inside the class body. 您在render()方法中定义了回调,而不是在类体内。 Do it like this: 像这样做:

class LoginForm extends Component {
    onEmailChange(text) {
            this.props.emailChanged(text);
    }        

    render() {
       return(...);
    }
}

Also you shouldn't bind methods inside your render() method. 此外,您不应该在render()方法中绑定方法。 Do it in the constructor of your Component: 在Component的构造函数中执行:

class LoginForm extends Component {
    constructor(props) {
        super(props);
        this.onEmailChange.bind(this);
    }

    onEmailChange(text) {
        // do something
    }

    // other methods
}

Or if you use babel and ES6, you can define your callback with an arrow function, then it will be automatically bound: 或者如果您使用babel和ES6,您可以使用箭头函数定义回调,然后它将自动绑定:

class LoginForm extends Component {

    onEmailChange = text => {
        // do something
    };

    // other methods
}

See also the react docs about autobinding . 另请参阅有关自动绑定反应文档

Also your call to connect seems incorrect. 您的连接调用似乎也不正确。 If you want to dispatch the action emailChanged it has to look like this: 如果你想发送动作emailChanged它必须如下所示:

const mapStateToProps = state =>  {
    return {
        email: state.auth.email
    };
};

const mapDispatchToProps = dispatch => {
    // this put a function emailChanged into your props that will dispatch the correct action
    emailChanged: text => dispatch(emailChanged(text))
}; 

const LoginFormContainer = connect(mapStateToProps, mapDispatchToProps)(LoginForm);    

export default LoginFormContainer;

The third argument to connect needs to be a function that knows how to merge the output of mapStateToProps , mapDispatchToProps , and ownProps all into one object that is then used as props for your connected component. connect的第三个参数需要是一个知道如何将mapStateToPropsmapDispatchToPropsownProps all的输出合并到一个对象中的mapDispatchToProps ,然后ownProps对象用作连接组件的props。 I think you're trying to pass that action to the mapDispatchToProps argument, which is the second argument not the third. 我想你正试图将该动作传递给mapDispatchToProps参数,这是第二个参数而不是第三个参数。 So, based on what I think you're doing, you probably wanna change your connect line to look like this. 所以,基于我认为你正在做的事情,你可能想要改变你的connect线看起来像这样。

export default connect(mapStateToProps, {emailChanged}) (LoginForm);

Then, export the function from your actions file not the output of calling that function. 然后,从您的操作文件导出该函数,而不是调用该函数的输出。

export default emailChanged;

Notice I removed the parentheses so it's not being called. 注意我删除了括号,因此没有被调用。

Then make the callback function a method on your class and bind it in the constructor. 然后将回调函数作为类的方法并将其绑定在构造函数中。

constuctor(props) {
  super(props);
  this.onEmailChange = this.onEmailChange.bind(this);
}

onEmailChange(text) {
  this.props.emailChanged(text);
}

Then update onChangeText on that element. 然后在该元素上更新onChangeText

onChangeText={this.onEmailChange}

Your connect is miswired 您的连接错误连接

connect(mapStateToProps, null, {emailChanged}) (LoginForm);

It should be something like: 它应该是这样的:

connect(mapStateToProps, 
       (dispatch) => ({emailChanged: (text) => dispatch(emailChanged(text))}) 
)(LoginForm);

so that your action actually gets dispatched 这样你的行动实际上就会被派遣出来

and as spotted by emed in comment: 并且由评论中的emed发现:

export default emailChanged;

without parentheses. 没有括号。

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

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