Binding buttons in SPFx

When writing a react based SPFx application one has to make a note that ES6 React.Component doesn’t auto bind methods to itself.

Hence it’s required to manually bind and the following are two ways to do it.

Method 1

onClick={this.addButtonClicked.bind(this)}

import * as React from 'react';

import { Stack, IStackProps, IStackStyles } from 'office-ui-fabric-react/lib/Stack';
import { ActionButton } from 'office-ui-fabric-react/lib/Button';
import { IIconProps } from 'office-ui-fabric-react/';

import { ITestComponentState } from './ITestComponentState';
import { ITestComponentProps } from './ITestComponentProps';

//Stack related styles
const outerStackTokens = {
    childrenGap: 50
};
const addFriendIcon: IIconProps = { iconName: 'Add' };

let outerStackStyles: Partial<IStackStyles> = {};
let innerStackColumnProps: Partial<IStackProps> = {};

export default class TestComponent extends React.Component<ITestComponentProps, ITestComponentState> {
    constructor(props: ITestComponentProps) {
        super(props);
        this.state = {
            items: []
        };
    }
  
    public render(): React.ReactElement<{}> {
        return (
            <div>
                <Stack horizontal tokens={outerStackTokens} styles={outerStackStyles}>
                    <Stack verticalAlign="start" {...innerStackColumnProps}>
                        <Stack.Item align="start" >
                            <ActionButton iconProps={addFriendIcon} onClick={this.addButtonClicked.bind(this)} allowDisabledFocus disabled={this.state.sortItems.length >= 10 ? true : false} >Add Item</ActionButton>
                        </Stack.Item>
                    </Stack>
                </Stack>
            </div>
        );
    }

    private addButtonClicked(event?: React.MouseEvent<HTMLButtonElement>) {
        let itemsOnAdd = this.state.items;
        let itemTitle = "Item " + (this.state.items.length + 1);
        itemsOnAdd.push({ title: itemTitle });
        this.setState({ items: itemsOnAdd });
    }
}

Method 2

this.addButtonClicked = this.addButtonClicked.bind(this);

import * as React from 'react';

import { Stack, IStackProps, IStackStyles } from 'office-ui-fabric-react/lib/Stack';
import { ActionButton } from 'office-ui-fabric-react/lib/Button';
import { IIconProps } from 'office-ui-fabric-react/';

import { ITestComponentState } from './ITestComponentState';
import { ITestComponentProps } from './ITestComponentProps';

//Stack related styles
const outerStackTokens = {
    childrenGap: 50
};
const addFriendIcon: IIconProps = { iconName: 'Add' };

let outerStackStyles: Partial<IStackStyles> = {};
let innerStackColumnProps: Partial<IStackProps> = {};

export default class TestComponent extends React.Component<ITestComponentProps, ITestComponentState> {
    constructor(props: ITestComponentProps) {
        super(props);
        this.state = {
            items: []
        };
        this.addButtonClicked = this.addButtonClicked.bind(this);
    }
  
    public render(): React.ReactElement<{}> {
        return (
            <div>
                <Stack horizontal tokens={outerStackTokens} styles={outerStackStyles}>
                    <Stack verticalAlign="start" {...innerStackColumnProps}>
                        <Stack.Item align="start" >
                            <ActionButton iconProps={addFriendIcon} onClick={this.addButtonClicked} allowDisabledFocus disabled={this.state.sortItems.length >= 10 ? true : false} >Add Item</ActionButton>
                        </Stack.Item>
                    </Stack>
                </Stack>
            </div>
        );
    }

    private addButtonClicked(event?: React.MouseEvent<HTMLButtonElement>) {
        let itemsOnAdd = this.state.items;
        let itemTitle = "Item " + (this.state.items.length + 1);
        itemsOnAdd.push({ title: itemTitle });
        this.setState({ items: itemsOnAdd });
    }
}