Blueprint: Toast api seems to violate core React principles

Created on 13 Jun 2017  路  6Comments  路  Source: palantir/blueprint

Discussion

  • __Package version(s): 1.17.1

Toasts and the Toaster component api do not to follow standard React data flow. Most of the blueprint component api (and indeed most React components) allow data and configuration to be passed to components via props. The Toaster component api relies on the methods exposed on a reference to the component in order to manage the component. As evidenced by #1205, the dom manipulation underneath Toaster.create and Toaster.show are also not intuitive React behavior - they manipulate the dom outside of the react render cycle.

My guess is that the behavior of self-dismissing, ephemeral toasts is part of the design of the component, and that behavior doesn't sync well with a component api based exclusively on props.

Toaster api from docs

import { Button, Position, Toaster } from "@blueprintjs/core";

class MyComponent extends React.Component<{}, {}> {
    private toaster: Toaster;
    private refHandlers = {
        toaster: (ref: Toaster) => this.toaster = ref,
    };

    public render() {
        return (
            <div>
                <Button onClick={this.addToast} text="Procure toast" />
                <Toaster position={Position.TOP_RIGHT} ref={this.refHandlers.toaster} />
            </div>
        )
    }

    private addToast = () => {
        this.toaster.show({ message: "Toasted!" });
    }
}

What I would expect from a 'standard' react component api

import { Button, Position, Toaster } from "@blueprintjs/core";

class MyComponent extends React.Component<{}, {}> { 
    constructor(props) {
        super(props)
        this.state = {
            toasts: []
        }
   }

    public render() {
        return (
            <div>
                <Button onClick={this.addToast} text="Procure toast" />
                <Toaster position={Position.TOP_RIGHT} toasts={this.state.toasts} />
            </div>
        )
    }

    private addToast = () => {
        this.setState({
             toasts: [{message: "Toasted!" }]
        });
    }
}

I'd love to know more about the design decisions that went into this component, how it is used or intended to be used in apps where toasts are stored in data, and what the future of this component looks like. Will there be a Toaster component exposed that takes messages as props? I'd like to manage toast data independent of how it is rendered.

core question

Most helpful comment

@rrcobb @shahzeb1 @studioraygun I think there are two action items to resolve this issue:

  1. better docs about usage patterns (see comment above).
  2. support controlled <Toaster toasts={...} /> prop because React.

All 6 comments

Heavily seconded. The current form actually makes it much more complicated for those using non-typescript js.

Agreed. I haven't a clue how to even implement Toasts currently!

my preferred pattern for toasts is as follows:

toaster.ts

import { Position, Toaster } from "@blueprintjs/core";

/** Singleton toaster instance. Create separate instances for different options. */
export const AppToaster = Toaster.create({
    className: "recipe-toaster",
    position: Position.TOP,
});

app.ts

import { Button } from "@blueprintjs/core";
import { AppToaster } from "./toaster";

export class App extends React.PureComponent {
    render() {
        return <Button onClick={this.showToast} text="Toast" />;
    }

    showToast = () => {
        // create toasts in response to interactions.
        // in most cases, it's enough to simply create and forget (thanks to timeout).
        AppToaster.show({ message: "Toasted." });
    }
}

@rrcobb @shahzeb1 @studioraygun I think there are two action items to resolve this issue:

  1. better docs about usage patterns (see comment above).
  2. support controlled <Toaster toasts={...} /> prop because React.

I'm fine with anything, as long as it is better documented for non-typescript folks. 馃挴

And truthfully, you could honestly just append this response into the docs and that would save a lot of people from having to come here to the issues.

Ah, that would explain it. I looked at .ts and thought "wut"

Was this page helpful?
0 / 5 - 0 ratings

Related issues

sunabozu picture sunabozu  路  3Comments

mdebeus picture mdebeus  路  3Comments

raiju picture raiju  路  3Comments

westrem picture westrem  路  3Comments

havesomeleeway picture havesomeleeway  路  3Comments