react-simple-snackbar

A really simple React snackbar component

Usage no npm install needed!

<script type="module">
  import reactSimpleSnackbar from 'https://cdn.skypack.dev/react-simple-snackbar';
</script>

README

React Simple Snackbar Logo

NPM Version Build Status Coverage Status Gzipped size JavaScript Style Guide MIT License

You can check a quick demo here.

Getting Started

Installation

npm install --save react-simple-snackbar

or

yarn add react-simple-snackbar

Basic Usage

First, you need to wrap your application into a SnackbarProvider:

// App.js
import React from 'react'
import SnackbarProvider from 'react-simple-snackbar'
import SomeChildComponent from './SomeChildComponent'

export default function App() {
  return (
    <SnackbarProvider>
      <SomeChildComponent />
    </SnackbarProvider>
  )
}

Then you can use both options on any descendant component:

1. useSnackbar() hook on function components

// SomeChildComponent.js
import React from 'react'
import { useSnackbar } from 'react-simple-snackbar'

export default function SomeChildComponent() {
  const [openSnackbar, closeSnackbar] = useSnackbar()

  return (
    <div>
      <button onClick={() => openSnackbar('This is the content of the Snackbar.')}>
        Click me to open the Snackbar!
      </button>
      <button onClick={closeSnackbar}>
        Click me to close the Snackbar programmatically.
      </button>
    </div>
  )
}

2. withSnackbar() HoC on class components

// SomeChildComponent.js
import React from 'react'
import { withSnackbar } from 'react-simple-snackbar'

class SomeChildComponent extends React.Component {
  render() {
    const { openSnackbar, closeSnackbar } = this.props

    return (
      <div>
        <button onClick={() => openSnackbar('This is the content of the Snackbar.')}>
          Click me to open the Snackbar!
        </button>
        <button onClick={closeSnackbar}>
          Click me to close the Snackbar programmatically.
        </button>
      </div>
    )
  }
}

export default withSnackbar(SomeChildComponent)

API

Methods

These methods are are returned from useSnackbar() hook in array destructuring syntax:

const [openSnackbar, closeSnackbar] = useSnackbar()

// You can also give different names as you wish
const [open, close] = useSnackbar()

Or added as additional props on components wrapped in withSnackbar():

const { openSnackbar, closeSnackbar } = this.props

openSnackbar(node [, duration])

  • node: the node you want to show into the Snackbar. It can be just "Some string like showed on Basic Usage", or <p>Some element you would <strong>like</strong> to show</p>.

  • duration: a number in milliseconds to set the duration of the Snackbar. The default value is 5000.

closeSnackbar()

  • This method is used if you want to close the Snackbar programmatically. It doesn't receive any params.

Options

You can pass an options object to customize your Snackbar. This object can be passed either in useSnackbar([options]) or as second argument of withSnackbar(Component [, options]). It accepts three options:

  • position: a custom position for your Snackbar. The default value is bottom-center, and the possible values are top-left, top-center, top-right, bottom-left, bottom-center and bottom-right.

  • style: a style object with camelCased properties and string values. These styles are applied to the Snackbar itself.

  • closeStyle: same as above, but the styles are applied to the close button. You can use font properties to style the X icon.

For example:

const options = {
  position: 'bottom-right',
  style: {
    backgroundColor: 'midnightblue',
    border: '2px solid lightgreen',
    color: 'lightblue',
    fontFamily: 'Menlo, monospace',
    fontSize: '20px',
    textAlign: 'center',
  },
  closeStyle: {
    color: 'lightcoral',
    fontSize: '16px',
  },
}

// Usage with hooks
useSnackbar(options)
// Usage with HoC
withSnackbar(Component, options)

Testing

The snackbar itself is already tested and you don't have to worry about it.

To test components that use Snackbar functionalities, there are some approaches as described bellow. This examples makes use of Jest and Enzyme for testing, but you can use whatever you want.

Testing components that use useSnackbar() hook

You can mock the implementation of useSnackbar to return an array containing openSnackbar and closeSnackbar as mocked functions:

// Component.test.js
import React from 'react'
import { shallow } from 'enzyme'
import * as Snackbar from 'react-simple-snackbar'
import Component from './Component'

// Mocks the open and close functions
const openSnackbarMock = jest.fn()
const closeSnackbarMock = jest.fn()
jest.spyOn(Snackbar, 'useSnackbar').mockImplementation(() => [openSnackbarMock, closeSnackbarMock])

it('can test the openSnackbar and closeSnackbar functions', () => {
  const wrapper = shallow(<Component />)

  // Simulates click on some buttons that opens and closes the Snackbar
  wrapper.find('button.open').simulate('click')
  wrapper.find('button.close').simulate('click')

  // Some examples of how you can test the mocks
  expect(openSnackbarMock).toHaveBeenCalled()
  expect(openSnackbarMock).toHaveBeenCalledTimes(1)
  expect(openSnackbarMock).toHaveBeenCalledWith('This is the text of the Snackbar.')
  expect(closeSnackbarMock).toHaveBeenCalled()
  expect(closeSnackbarMock).toHaveBeenCalledTimes(1)
})

Testing components wrapped in withSnackbar() HoC

To make it easier to test and not make use of SnackbarProvider, you can export your component in isolation as a named export, and as a default export wrapped in withSnackbar():

// Component.js

// (...)
// * Here goes all the component's code *
// (...)

// Named export for testing, and default export for using
export { Component }
export default withSnackbar(Component)

So you can get the component as a named import, then mock the openSnackbar and closeSnackbar functions as common props if you want:

// Component.test.js
import React from 'react'
import { shallow } from 'enzyme'
import { Component } from './Component'

it('can test the openSnackbar and closeSnackbar functions', () => {
  const openSnackbarMock = jest.fn()
  const closeSnackbarMock = jest.fn()
  const wrapper = shallow(
    <Component openSnackbar={openSnackbarMock} closeSnackbar={closeSnackbarMock} />
  )

  // Simulates click on some buttons that opens and closes the Snackbar
  wrapper.find('button.open').simulate('click')
  wrapper.find('button.close').simulate('click')

  // Some examples of how you can test the mocks
  expect(openSnackbarMock).toHaveBeenCalled()
  expect(openSnackbarMock).toHaveBeenCalledTimes(1)
  expect(openSnackbarMock).toHaveBeenCalledWith('This is the text of the Snackbar.')
  expect(closeSnackbarMock).toHaveBeenCalled()
  expect(closeSnackbarMock).toHaveBeenCalledTimes(1)
})

Contributing

See CONTRIBUTING for more information on how to get started.

License

React Simple Snackbar is open source software licensed as MIT.