Reactjs 未定义不是一个函数';onLogin';何时使用redux

Reactjs 未定义不是一个函数';onLogin';何时使用redux,reactjs,react-native,redux,react-redux,Reactjs,React Native,Redux,React Redux,我使用connect绑定操作'isLoading'和'onLogin',但是它没有定义,因为日志中没有定义'this.props'。我已经检查了很多次,我认为代码应该是好的,但我无法找出我在redux概念中遗漏了什么 下一个问题是“将参数传递到LoginButton.js中的容器是否正确?” 非常感谢有人能提出一些建议来帮助我,谢谢 我认为一些可能导致以下错误的文件 LoginButton.js import {loginStyles} from 'App/styles'; import {l

我使用
connect
绑定
操作'isLoading'和'onLogin'
,但是它没有定义,因为日志中没有定义'this.props'。我已经检查了很多次,我认为代码应该是好的,但我无法找出我在redux概念中遗漏了什么
下一个问题是“将参数传递到
LoginButton.js
中的容器是否正确?” 非常感谢有人能提出一些建议来帮助我,谢谢
我认为一些可能导致以下错误的文件

LoginButton.js

import {loginStyles} from 'App/styles';
import {loginUser} from 'App/redux/actions/actionCreators'


export const LoginButton = ({isLoading, onLogin, username, password }) => {
  let loginButton;
  console.log('props: ' + this.props);

  if (isLoading){
    loginButton = (
      <Button primary full rounded >
        <Spinner style={loginStyles.spinner} color='white'/>  
        <Text style={loginStyles.IconDivider}>Loading...</Text>
      </Button>  
    )
  }else{
    loginButton = (
      <Button primary full rounded 
          onPress={() => onLogin(username, password)}>
        <Text>Login</Text>
      </Button> 
    ) 
  }
  return loginButton;
}

const styles = StyleSheet.create({
  buttonContainer:{
    flex:1, 
    flexDirection:'row'
  }
})

const mapStateToProps = state => ({
    isLoading: state.auth.isLoading,
    username: state.auth.username,
    password: state.auth.password
});

const mapDispatchToProps = dispatch => ({
    onLogin: (username, password) => dispatch(loginUser(username, password))
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(LoginButton);
import {LoginButton} from 'App/components';

export class Login extends Component {
  constructor(props){
    super(props);

    this.state = {
      username: '',
      password: ''
    }
  }

  render() {

    return (
      <Container>
        <Content contentContainerStyle={styles.contentContainer}>
          <Image source={images.login} style={styles.bg}>
            <View style= {loginStyles.formContainer}>

              <InputGroup style={loginStyles.input}>
                <Icon name="ios-mail-outline" style={loginStyles.icon} />
                <Input
                  onChangeText={(username) => this.setState({username})}
                  value={this.state.username}
                  placeholder={"Email Address"} />             
              </InputGroup>

              <InputGroup style={loginStyles.input}>
                  <Icon name="ios-lock-outline" style={loginStyles.icon} />
                  <Input
                    onChangeText={(password) => this.setState({password})}
                    value={this.state.password}
                    secureTextEntry={true}
                    placeholder={"Password"} />              
              </InputGroup>

              <View style={loginStyles.button}>
                <LoginButton username={this.state.username} password={this.state.password}/>
              </View>
            </View>
          </Image>
        </Content>
      </Container>
    );
  }
}

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

export default connect(mapStateToProps, null)(Login);
function loginSuccess(username, password) {  
  return {
    type: types.LOGIN_SUCCESS,
    username: username,
    password: password
  }
}

function loginFailure(error) {  
  return {
    type: types.LOGIN_FAILURE,
    payload: error
  }
}

export function loginUser(username, password) {  
  return function(dispatch) {
    if (username == 'admin' && password == '123qwe'){
      dispatch(loginSuccess(username, password));
    }else{
      dispatch(loginFailure('Incorrect username or password'));
    }
  };
}
actionCreators.js

import {loginStyles} from 'App/styles';
import {loginUser} from 'App/redux/actions/actionCreators'


export const LoginButton = ({isLoading, onLogin, username, password }) => {
  let loginButton;
  console.log('props: ' + this.props);

  if (isLoading){
    loginButton = (
      <Button primary full rounded >
        <Spinner style={loginStyles.spinner} color='white'/>  
        <Text style={loginStyles.IconDivider}>Loading...</Text>
      </Button>  
    )
  }else{
    loginButton = (
      <Button primary full rounded 
          onPress={() => onLogin(username, password)}>
        <Text>Login</Text>
      </Button> 
    ) 
  }
  return loginButton;
}

const styles = StyleSheet.create({
  buttonContainer:{
    flex:1, 
    flexDirection:'row'
  }
})

const mapStateToProps = state => ({
    isLoading: state.auth.isLoading,
    username: state.auth.username,
    password: state.auth.password
});

const mapDispatchToProps = dispatch => ({
    onLogin: (username, password) => dispatch(loginUser(username, password))
});

export default connect(
  mapStateToProps,
  mapDispatchToProps
)(LoginButton);
import {LoginButton} from 'App/components';

export class Login extends Component {
  constructor(props){
    super(props);

    this.state = {
      username: '',
      password: ''
    }
  }

  render() {

    return (
      <Container>
        <Content contentContainerStyle={styles.contentContainer}>
          <Image source={images.login} style={styles.bg}>
            <View style= {loginStyles.formContainer}>

              <InputGroup style={loginStyles.input}>
                <Icon name="ios-mail-outline" style={loginStyles.icon} />
                <Input
                  onChangeText={(username) => this.setState({username})}
                  value={this.state.username}
                  placeholder={"Email Address"} />             
              </InputGroup>

              <InputGroup style={loginStyles.input}>
                  <Icon name="ios-lock-outline" style={loginStyles.icon} />
                  <Input
                    onChangeText={(password) => this.setState({password})}
                    value={this.state.password}
                    secureTextEntry={true}
                    placeholder={"Password"} />              
              </InputGroup>

              <View style={loginStyles.button}>
                <LoginButton username={this.state.username} password={this.state.password}/>
              </View>
            </View>
          </Image>
        </Content>
      </Container>
    );
  }
}

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

export default connect(mapStateToProps, null)(Login);
function loginSuccess(username, password) {  
  return {
    type: types.LOGIN_SUCCESS,
    username: username,
    password: password
  }
}

function loginFailure(error) {  
  return {
    type: types.LOGIN_FAILURE,
    payload: error
  }
}

export function loginUser(username, password) {  
  return function(dispatch) {
    if (username == 'admin' && password == '123qwe'){
      dispatch(loginSuccess(username, password));
    }else{
      dispatch(loginFailure('Incorrect username or password'));
    }
  };
}

我注意到有两件事可能会导致代码出现问题:

  • 您正在创建一个无状态的
    组件,但您正在尝试登录
    
    此.props
    无法使用,因为您不在
    类中
    组件中不需要任何
    道具
    参数 功能签名:

    export const LoginButton = ({isLoading, onLogin, username, password }) => {...
    
  • LoginButton.js
    中,您正在导出命名对象
    LoginButton
    除了默认导出之外,默认导出是 连接到redux

    export default connect(
      mapStateToProps,
      mapDispatchToProps
    )(LoginButton);
    
    import {LoginButton} from 'App/components';  
    
    但是在
    Login.js
    中,您正在导入命名的导出(它不是 连接到
    redux
    ):

    您应该将其更改为默认导入语法:

    import LoginButton from 'App/components';
    

  • 感谢您的快速回复,您的意思是如果我将“const login button”更改为class component,可以吗?这不是真正的问题,现在,你可以直接访问参数,而不是
    这个.props
    你现在正在做的
    isLoading
    onlogin
    等等。你真正的问题是你没有使用
    登录按钮的连接组件
    只需像这样导入它:
    从“App/components”导入登录按钮而不是这个:
    从'App/components'导入{LoginButton}
    注意
    {}