在我的应用程序中,主要组件定义了一个函数,该函数具有对本地函数的引用,如下所示:
class Root extends React.Component {
constructor(props) {
super(props);
}
tokenizer({email, password}) {
return this.props.client.query({
query: getToken,
variables: {email: email, password: password}
}).then(response => {
return response.data
}).catch(error => {
console.warn(error);
return {}
});
}
async fetchToken({email, password}) {
const data = await this.tokenizer({email, password});
this.props.updateToken({token: data.login});//redux dispatch to props
}
render() {
if (this.props.token) {
return (
<Home />
)
} else {
return <Login fetchToken={this.fetchToken} />;
}
}
}
子组件(即Login
)将使用fetchToken
函数,如下所示:
class Login extends Component {
constructor(props) {
super(props);
this.state = {
email: '',
password: ''
};
this.handleChange = this.handleChange.bind(this);
this.handleSubmit = this.handleSubmit.bind(this);
}
handleChange(event) {
this.setState({[event.target.name]: event.target.value});
}
handleSubmit(event) {
event.preventDefault();
this.props.fetchToken(this.state);
}
render() {
return (
<Form onSubmit={this.handleSubmit}>
// ... Form HTML here
</Form>
)
}
}
现在,一旦提交表单,根据以下错误,fetchToken
将无法引用this.tokenizer
:Uncaught (in promise) TypeError: this.tokenizer is not a function
我可以通过tokenizer
方法,但是它又引用了其他道具。因此,我必须通过任何与功能/状态/道具相关的功能,这感觉像是一种过大的功能。相反,只能通过在父级中引用fetchToken
来调用它吗?
答案 0 :(得分:1)
如果要在同一上下文中使用它们,则必须绑定所有方法。 最简单的方法是在类中为每种方法使用箭头功能。
class Root extends React.Component {
tokenizer = async ({email, password}) => {
return this.props.client.query({
query: getToken,
variables: {email: email, password: password}
}).then(response => {
return response.data
}).catch(error => {
console.warn(error);
return {}
});
}
fetchToken = async ({email, password}) => {
const data = await this.tokenizer({email, password});
this.props.updateToken({token: data.login});//redux dispatch to props
}
render() {
if (this.props.token) {
return (
<Home />
)
} else {
return <Login fetchToken={this.fetchToken} />;
}
}
}
答案 1 :(得分:1)
fetchToken
没有引用this
,因此您必须绑定它或使用箭头函数。要绑定它,您必须像在登录组件的构造函数中使用this
和handleChange
一样将其绑定到handleSubmit
。
作为箭头功能,您的fetchToken
如下所示:
async fetchToken = ({email, password}) => {
const data = await this.tokenizer({email, password});
this.props.updateToken({token: data.login});//redux dispatch to props
}
我建议对令牌生成器进行同样的操作。
答案 2 :(得分:0)
如错误所示,执行以下代码行时出现类型错误:
const data = await this.tokenizer({email, password});
您正在使用tokenizer
调用this
函数,但实际上this
现在并不指向同一对象。如果您console.log(this.tokenizer)
,它将给您undefined
。是的您发现问题在于范围。让我向您介绍一下this
的范围:
当它在对象方法内部时,函数的所有者就是对象。因此,this
关键字已绑定到对象。
然而,当它在一个函数内部,独立函数或另一个函数内部时,this
将始终引用全局范围。
这被称为 JavaScript怪癖,这意味着JavaScript中发生的某些事情并不十分简单,并且无法按照您的想法进行。开发人员还认为这是一个糟糕的设计选择,现在他们正在使用ES6的箭头功能进行补救。
您可以绑定开发人员在ES6之前使用的方法,或者现在只需使用箭头功能即可。像这样
async fetchToken = ({email, password}) => {
const data = await this.tokenizer({email, password});
this.props.updateToken({token: data.login});//redux dispatch to props
}
类似地,您可以使标记程序功能也像箭头功能一样。