我重构了一个从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);
单击登录按钮会调用登录功能,但出于某种原因,this
为null
谢谢你看看
答案 0 :(得分:7)
React不会绑定添加到ES6类的方法的上下文,除非它们是标准React生命周期(componentWillReceiveProps
,componentDidMount
等)的一部分。
这意味着您需要为this
,signUp
和logIn
方法手动绑定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/
简而言之,您有几个选择:
(相当常见/流行)在构造函数中将您的方法绑定到此。您可能不需要绑定所有方法 - 取决于它们的使用方式。
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);
}
将您的方法定义为箭头函数,将它绑定到当前作用域 - 无需在构造函数中绑定它们:
class Home extends Component {
// ...
signUp = () => {
this.props.dispatch(signUp(this.state.registration));
this.setState({
registration: {},
});
}
// ...
}