On a React login page, I created a class for rendering authentication methods. The class includes a default render function that I need to customize.
class AuthMethod {
constructor(initializer: Pick<AuthMethod, 'id'> & Partial<AuthMethod>) {
Object.assign(this, initializer);
}
id!: string;
text: string = "";
enabled: boolean = false;
icon: React.ReactNode = React.Fragment;
render: () => React.ReactNode = () => (
<WhiteIconButton key={this.id} disabled={!this.enabled} >
{this.icon}
</WhiteIconButton>
);
}
I have an array of these AuthMethod instances for different purposes:
const authMethods: AuthMethod[] = [
new AuthMethod({
id: "auth_facebook",
text: "Sign in with Facebook",
enabled: false,
icon: <FontAwesomeIcon icon={faFacebookSquare} />,
// render: () => this.icon // This doesn't work
}),
new AuthMethod({
id: "auth_twitter",
text: "Sign in with Twitter",
enabled: false,
icon: <FontAwesomeIcon icon={faTwitter} />
}),
new AuthMethod({
id: "auth_google",
text: "Sign in with Google",
enabled: true,
icon: <FontAwesomeIcon icon={faGoogle} />
})
];
To render them, I use the following code:
<div className={classes.socialLine}>
{ authMethods.map(m => m.render()) }
</div>
The issue arises when trying to override the "render" arrow function with one that utilizes the class properties. If I uncomment the "render:" line in the Facebook example, I receive an error stating "The containing arrow function captures the global value of 'this'".
How can I access member properties within the supplied arrow function?
Edit: To see the problem, you can run the code here: https://codesandbox.io/s/tender-bhabha-8jdmf?fontsize=14&hidenavigation=1&theme=dark
Simply uncomment the "render: " line to encounter the issue.
Solution:
Credit goes to jcalz for providing the answer that arrow functions do not have access to the "this" property (as it is bound to the context where it is created). Therefore, using a regular function (non-arrow) resolves the issue. Despite the class definition having an arrow function signature, a "normal" function works fine as shown below:
new AuthMethod({
id: "auth_facebook",
text: "Sign in with Facebook",
enabled: false,
icon: <FontAwesomeIcon icon={faFacebookSquare} />,
render: function() {
return this.icon;
}
}),
You can view the solution in action here: