Search code examples
javascriptreactjsflux

React + Flux data errors produce snackbar notification?


Similar to this question, I'm using material UI and React, and I want to display a Snackbar notification on data error.

The notable difference is I'm doing this in a fairly stock Flux way, not Redux.

Specifically, if a fetch operation can't connect to the backend servers, I want to display a snackbar notification informing the user.

In my understanding of Flux, the UI emits actions which affect stores, in a one-way fashion. Since the error is happening in the data store asyncronously, how do I bubble the error up to the snackbar?

action

export default {
  loginUser: () => {
    AppDispatcher.dispatch({ actionType: LOGIN });
  }
}

store

class LoginStore extends EventEmitter {
  constructor() {
    super()
    this.snackbarError = undefined
  }
  _registerToActions(action) {
    switch(action.actionType) {
      case LOGIN:
        fetch('/auth').catch((error) => {
          this.snackbarError = 'Auth failed!'
        })
        this.emitChange();
        break;
      }
    }
  }
}

component

class MyComponent extends React.Component {

  // how do I trigger snackbar.show() when LoginStore.snackbarError set?

  render (
    <h3>My Component</h3>
    <button onClick={LoginAction.loginUser}>Login</button>
    <Snackbar message={LoginStore.snackbarError} />
  )
}

Solution

  • Something like this

    class LoginStore extends EventEmitter {
      constructor() {
        super()
        this.snackbarError = undefined
      }
      _registerToActions(action) {
        switch(action.actionType) {
          case LOGIN:
            fetch('/auth').catch((error) => {
              this.snackbarError = 'Auth failed!'
              this.emitSomeWhoCallMyComponent();
            })
    
            break;
          }
        }
      }
    }
    

    and

    class MyComponent extends React.Component {
    
      // how do I trigger snackbar.show() when LoginStore.snackbarError set?
      componentDidMount()
      {
        this._doSomething = () => doSomething();
        LoginStore.addSomeWhoCallMyComponentListener(this._doSomething);
      }
    
      doSomething()
      {
        snackbar.show();
      }
      render (
        <h3>My Component</h3>
        <button onClick={LoginAction.loginUser}>Login</button>
        <Snackbar message={LoginStore.snackbarError}  />
      )
    }