Javascript 为什么会出现无效值错误?
我不明白我是如何得到这个错误的(下图)。在我的Javascript 为什么会出现无效值错误?,javascript,ios,reactjs,react-native,redux,Javascript,Ios,Reactjs,React Native,Redux,我不明白我是如何得到这个错误的(下图)。在我的LoginForm.js文件中,当我在WebStormIDE中将鼠标悬停在onEmailChange()上时,onEmailChange(text)给了我一个未解析的函数或方法调用。在我的index.js文件中,任何地方都不会抛出错误 我已经环顾四周,寻找这个问题,但它与我的问题并不完全相关 我尝试了文件>使缓存无效/重新启动,但没有成功 下面是App.js的 import React, { Component } from 'react'; im
LoginForm.js
文件中,当我在WebStorm
IDE中将鼠标悬停在onEmailChange()上时,onEmailChange(text)
给了我一个未解析的函数或方法调用。在我的index.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;
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);
import {EMAIL_CHANGED} from './types';
export const emailChanged = (text) => {
return {
type: 'EMAIL_CHANGED',
payload: text
};
};
export default emailChanged();
下面是index.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;
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);
import {EMAIL_CHANGED} from './types';
export const emailChanged = (text) => {
return {
type: 'EMAIL_CHANGED',
payload: text
};
};
export default emailChanged();
您在render()
方法中定义了回调,而不是在类主体中。这样做:
class LoginForm extends Component {
onEmailChange(text) {
this.props.emailChanged(text);
}
render() {
return(...);
}
}
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;
另外,您不应该在render()方法中绑定方法。在组件的构造函数中执行此操作:
class LoginForm extends Component {
constructor(props) {
super(props);
this.onEmailChange.bind(this);
}
onEmailChange(text) {
// do something
}
// other methods
}
或者,如果您使用babel和ES6,您可以使用arrow函数定义回调,然后它将自动绑定:
class LoginForm extends Component {
onEmailChange = text => {
// do something
};
// other methods
}
另见
此外,您的连接呼叫似乎不正确。如果要发送操作emailChanged
,它必须如下所示:
class LoginForm extends Component {
onEmailChange(text) {
this.props.emailChanged(text);
}
render() {
return(...);
}
}
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;
您在render()
方法中定义了回调,而不是在类主体中。这样做:
class LoginForm extends Component {
onEmailChange(text) {
this.props.emailChanged(text);
}
render() {
return(...);
}
}
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;
另外,您不应该在render()方法中绑定方法。在组件的构造函数中执行此操作:
class LoginForm extends Component {
constructor(props) {
super(props);
this.onEmailChange.bind(this);
}
onEmailChange(text) {
// do something
}
// other methods
}
或者,如果您使用babel和ES6,您可以使用arrow函数定义回调,然后它将自动绑定:
class LoginForm extends Component {
onEmailChange = text => {
// do something
};
// other methods
}
另见
此外,您的连接呼叫似乎不正确。如果要发送操作emailChanged
,它必须如下所示:
class LoginForm extends Component {
onEmailChange(text) {
this.props.emailChanged(text);
}
render() {
return(...);
}
}
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;
连接的第三个参数需要是一个函数,它知道如何将MapStateTrops
、mapDispatchToProps
和ownProps
的输出合并到一个对象中,然后作为连接组件的道具使用。我认为您试图将该操作传递给mapDispatchToProps
参数,这是第二个参数,而不是第三个参数。所以,根据我认为你在做的事情,你可能想把你的connect
线路改成这样
export default connect(mapStateToProps, {emailChanged}) (LoginForm);
然后,从操作文件导出函数,而不是调用该函数的输出
export default emailChanged;
注意,我删除了括号,所以没有调用它
然后使回调函数成为类上的方法,并将其绑定到构造函数中
constuctor(props) {
super(props);
this.onEmailChange = this.onEmailChange.bind(this);
}
onEmailChange(text) {
this.props.emailChanged(text);
}
然后在该元素上更新onChangeText
onChangeText={this.onEmailChange}
连接的第三个参数需要是一个函数,它知道如何将MapStateTrops
、mapDispatchToProps
和ownProps
的输出合并到一个对象中,然后作为连接组件的道具使用。我认为您试图将该操作传递给mapDispatchToProps
参数,这是第二个参数,而不是第三个参数。所以,根据我认为你在做的事情,你可能想把你的connect
线路改成这样
export default connect(mapStateToProps, {emailChanged}) (LoginForm);
然后,从操作文件导出函数,而不是调用该函数的输出
export default emailChanged;
注意,我删除了括号,所以没有调用它
然后使回调函数成为类上的方法,并将其绑定到构造函数中
constuctor(props) {
super(props);
this.onEmailChange = this.onEmailChange.bind(this);
}
onEmailChange(text) {
this.props.emailChanged(text);
}
然后在该元素上更新onChangeText
onChangeText={this.onEmailChange}
你的连接线接错了
connect(mapStateToProps, null, {emailChanged}) (LoginForm);
应该是这样的:
connect(mapStateToProps,
(dispatch) => ({emailChanged: (text) => dispatch(emailChanged(text))})
)(LoginForm);
这样你的动作就可以被调度了
正如emed在评论中指出的:
export default emailChanged;
没有括号 您的连接线连接错误
connect(mapStateToProps, null, {emailChanged}) (LoginForm);
应该是这样的:
connect(mapStateToProps,
(dispatch) => ({emailChanged: (text) => dispatch(emailChanged(text))})
)(LoginForm);
这样你的动作就可以被调度了
正如emed在评论中指出的:
export default emailChanged;
没有括号 是否应该更改导出默认电子邮件代码>?如果包含()
,则表示正在执行函数并导出对象。是否应更改导出默认值代码>?如果包含()
,则表示正在执行函数并导出对象。我尝试了此操作,但每次写入导出默认值时,都会发生更改
并将鼠标悬停在它上面,它会给我一个未使用的默认导出emailChanged
。它应该没有括号。你也错过了如何使用康涅狄格的整个章节。我尝试过这个,但每当我写导出默认邮件时,它都会改变
并将鼠标悬停在它上面,它会给我一个未使用的默认导出emailChanged
。它应该没有括号。你还错过了如何使用康涅狄格的整个章节,但这对我来说不起作用。将回调函数设为箭头函数。尝试了一下,也没用。每当我将鼠标悬停在导出默认电子邮件更改上时,我都会收到未使用的默认导出电子邮件更改
代码>。您可能需要将mapDispatchToProps
作为一个函数,并将动作创建者包装在一个函数中,该函数将分派调用动作创建者的输出。同时尝试将回调函数设置为类上的一个方法。我知道你要去哪里,但这对我不起作用。将回调函数设置为箭头函数。尝试过之后,它也不起作用。每当我将鼠标悬停在导出默认电子邮件更改上时,我都会收到未使用的默认导出电子邮件更改
代码>。然后,您可能需要将mapDispatchToProps
设置为一个函数,并将动作创建者封装在一个函数中,该函数用于分派调用动作创建者的输出。此外,还可以尝试将回调函数设为类上的一个方法。