在React类函数

时间:2017-03-12 16:28:50

标签: javascript reactjs ecmascript-6 react-redux

我重构了一个从ES5到ES6的我的React类,现在当我点击一个调用this.state.dispatch(logIn(this.state.logIn))的按钮时,该行开头的初始this为空。超级奇怪。

这是我的班级:

class Home extends Component {
    constructor(props) {
        super(props);

        this.state = {
            panelIsOpen: false,
            registration: {},
            login: {},
        };
    }

    signUp() {
        this.props.dispatch(signUp(this.state.registration));

        this.setState({
            registration: {},
        });
    }

    logIn() {
        debugger; // this is `null here`
        this.props.dispatch(logIn(this.state.login));

        this.setState({
            login: {},
        });
    }

    togglePanel(e) {
        this.setState({ panelIsOpen: !this.state.panelIsOpen} );
    }

    render() {
        const {elements} = this.props;
        const {registration, login} = this.state;

        return (
            // some stuff 
        );
    }
};

Home.propTypes = {
    elements: React.PropTypes.array,
    dispatch: React.PropTypes.func,
    user: React.PropTypes.object,
};

const mapStateToProps = ({elements, auth}) => {
    return {
        elements: getElementsByKeyName(elements, 'visibleElements'),
        user: getLoggedInUser(auth),
    };
};

Home = DragDropContext(HTML5Backend)(Home);
export default connect(mapStateToProps)(Home);

单击登录按钮会调用登录功能,但出于某种原因,thisnull

谢谢你看看

2 个答案:

答案 0 :(得分:7)

React不会绑定添加到ES6类的方法的上下文,除非它们是标准React生命周期(componentWillReceivePropscomponentDidMount等)的一部分。

这意味着您需要为thissignUplogIn方法手动绑定togglePanel的值,或者将它们声明为箭头函数,继承父上下文。

1

constructor(props) {
  super(props);
  this.signUp = this.signUp.bind(this);
  this.logIn = this.logIn.bind(this);
  this.togglePanel = this.togglePanel.bind(this);

  this.state = {
    panelIsOpen: false,
    registration: {},
    login: {},
  }

2

signUp = () => {
  this.props.dispatch(signUp(this.state.registration));

  this.setState({
    registration: {},
  });
}

// the same for logIn and togglePanel

供参考,请参阅the docs

答案 1 :(得分:1)

这(没有双关语)与ES6中的函数绑定方式有关。如果您将方法作为道具传递给另一个组件,那么它所运行的上下文并不能保证是正确的上下文(除非您首先绑定它)。这篇文章有一篇长篇但有趣的读物:http://reactkungfu.com/2015/07/why-and-how-to-bind-methods-in-your-react-component-classes/

简而言之,您有几个选择:

  1. (相当常见/流行)在构造函数中将您的方法绑定到此。您可能不需要绑定所有方法 - 取决于它们的使用方式。

    constructor(props) {
        super(props);
        this.state = {
            panelIsOpen: false,
            registration: {},
            login: {},
        };
        this.signUp = this.signUp.bind(this);
        this.signUp = this.logIn.bind(this);
        this.togglePannel = this.togglePannel.bind(this);
    } 
    
  2. 将您的方法定义为箭头函数,将它绑定到当前作用域 - 无需在构造函数中绑定它们:

    class Home extends Component {
        // ...
    
        signUp = () => {
            this.props.dispatch(signUp(this.state.registration));
    
            this.setState({
                registration: {},
            });
        }
    
        // ...
    }