Friday, May 18, 2018

Mutating React state

This won't work. React can't detect mutation when done this way:
interface IComponentState
{
    numberList: number[];
}

export class HomeComponent extends React.Component<ComponentProps, IComponentState>
{
    private addNumber(): void
    {
        this.state.numberList.push(Math.random());
    }
}

This works, but would have to produce immutable explicitly:
private addNumber(): void
{
    const newArray = [...this.state.numberList, Math.random()];
    this.setState({numberList: newArray});    
}


Producing immutable the convenient way, use immer:
private addNumber(): void
{
    // https://github.com/DefinitelyTyped/DefinitelyTyped/issues/18365#issuecomment-390110697

    this.setState(produce<IComponentState>(draft => {
        draft.numberList.push(Math.random());
    }));
}


Deleting an element from an array:
{this.state.numberList.map((n, i) =>
    <div key={i}>
        {n}
        <button
            // tslint:disable jsx-no-lambda
            onClick={() => {
                this.state.numberList.splice(i, 1);
            }}
        >
            Non-working delete
        </button>

        <button
            // tslint:disable jsx-no-lambda
            onClick={() => {
                this.setState({
                    numberList: [
                        ...this.state.numberList.slice(0, i),
                        ...this.state.numberList.slice(i + 1)
                    ]
                });
            }}
        >
            Delete using explicit immutable
        </button>

        <button
            // tslint:disable jsx-no-lambda
            onClick={() => {
                this.setState(produce<IComponentState>(draft => {
                    draft.numberList.splice(i, 1);
                }));
            }}
        >
            Delete the easier way
        </button>
    </div>
)}



Happy Coding!

No comments:

Post a Comment