Trouble using actions in react-redux presentationa

2019-07-26 14:22发布

问题:

I'm new to redux and having trouble wrapping my head around presentational and container components.

Relevant stack:

  • react v0.14.8
  • react-native v0.24.1
  • redux v3.5.2
  • react-redux v4.4.5

The issue:

I have a login button component, which when rendered checks the login status and calls the onSuccessfulLogin action which updates the state with the user's Facebook credentials.

However, when trying to separate this into separate presentational/container components, I'm unable to call the onSuccessfulLogin action: Error: onSuccessfulLogin is not defined.

What am I doing wrong here? I'd imagine there's something simple that I'm not understanding with the relationship between the two components and the connect() function.

Presentational Component (Login.js)

import React, { PropTypes } from "react-native";
import FBLogin from "react-native-facebook-login";
import UserActions from "../users/UserActions";

class LoginPage extends React.Component {

    render() {

        const { userData, onSuccessfulLogin } = this.props;

        return (
          <FBLogin
              permissions={["email","user_friends"]}
              onLoginFound= { data => {
                  onSuccessfulLogin(data.credentials);
              }}
              />
        )
    }
};

export default LoginPage;

Container Component (LoginContainer.js)

import { connect } from 'react-redux';
import LoginPage from "../login/LoginPage";
import UserActions from "../users/UserActions";

const mapDispatchToProps = (dispatch) => {
  return {
    onSuccessfulLogin: (userData) => {
      dispatch(UserActions.userLoggedIn(userData))
    }
  }
}

const mapStateToProps = (state) => {
  return {
    userData: state.userData
  }
}

const LoginContainer = connect(
  mapStateToProps,
  mapDispatchToProps
)(LoginPage);

export default LoginContainer;

Also, if I wanted to make the updated state.userData accessible to the LoginPage component, how would I do that? Any help is appreciated!

Solved! When using ES6 classes, you're required to call super(props) in a constructor method in order to access the container's properties in the connected presentational component:

class LoginPage extends React.Component {
    constructor(props){
        super(props);
    }

    render(){    
        // ...
    }
}

回答1:

Your container component is supposed to be a component and it must have a render function with the dumb/presentational components you want to render.

import { connect } from 'react-redux';
import LoginPage from "../login/LoginPage";
import UserActions from "../users/UserActions";


class LoginContainer extends React.Component {
    constructor(props){
      super(props);
    }
    render() {
        return (
          <LoginPage userData={this.props.userData}
              onSuccessfulLogin={this.props.onSuccessfulLogin}
              />
        )
    }
};

const mapDispatchToProps = (dispatch) => {
  return {
    onSuccessfulLogin: (userData) => {
      dispatch(UserActions.userLoggedIn(userData))
    }
  }
}

const mapStateToProps = (state) => {
  return {
    userData: state.userData
  }
}


export default connect(
  mapStateToProps,
  mapDispatchToProps
)(LoginPage);