@webstrop/keep

1.0.12 • Public • Published

@webstrop/keep 🇩🇪

@webstrop/keep

This library is a foundation stone for data loading in your React App.

  • API architecture agnostic (you can use REST, GraphQL or even smoke signals)
  • Hooks
  • All actions in redux
  • SSR fully supported
  • Typescript types included

The principle aka how it works

Basically in every app you can do two actions with data:

  • ⬇️ load data
  • ↪️ trigger a action, called "mutation" (name borrowed from GraphQL)

This library will give you:

  • Redux actions/reducer/selectors for loading and mutations
  • Hooks for connection your app with data and request loading in component
  • Context Provider for client and server

This library doesn't include any support for data loading. Your job is to listen for redux actions and make API requests as sideffect!

Usage

Component:

import { useFetch, useMutate } from '@webstrop/keep'

const DogListContainer = (): JSX.Element => {
  // first argument is key to redux store, last is array of dependencies, every other is you own
  // and will be included to redux action as a field "args"
  const { isLoading, data, error } = useFetch('DogList', 'allDogs', ['name', 'image {publicUrl}'], [])
  // you can use useFetch multiple times
  const { isLoading: isLoadingCats, data: catsData, error: errorCats } = useFetch('CatList', 'allCats', ['name', 'image {publicUrl}'], [])
  // this function "toDinosaur" receives arbitrary object as a first argument.
  // it will be included to redux action as a field "payload"
  const toDinosaur = useMutate('DogList', 'DogtoDinosaur', ['T-Rex'])
  return <DogList isLoading={isLoading} list={data} error={error} onClick={toDinosaur} />
}

Redux middleware for making requests:

import { actions, actionTypes, promiseControlSymbol, FetchAction } from '@webstrop/keep'

const middleware = (store: Store) => (next: (action: FetchAction) => void) => (action: FetchAction) => {
  if (action.type === actionTypes.fetchStart) {
    // your fetch function
    handleFetch(store.dispatch, action[promiseControlSymbol], action.key, action.args)
  }
  if (action.type === actionTypes.mutateStart) {
    // your fetch function
    handleMutation(store.dispatch, action[promiseControlSymbol], action.key, action.args, action.payload)
  }
  return next(action)
}

Installation

This library:

yarn add @webstrop/keep

Peer dependencies (necessary):

use-sse@^2.0.1 redux react-redux

App root for Client

import { createClientProvider } from '@webstrop/keep'
import { Store } from 'redux'
import BareApp from './BareApp'

interface Props {
  store: Store
}

const KeepClientProvider = createClientProvider()

function App({ store }: Props) {
  return (
    <KeepClientProvider>
      <ReduxProvider store={store}>
        <BareApp /> {/** this is your app */}
      </ReduxProvider>
    </KeepClientProvider>
  )
}

export default App

Rendering on server

// example for express server
import { serverRender } from '@webstrop/keep'
import express from 'express'
import App from './src/App' // your React app

server
  .get('/*', async (req, res) => {
    const store = createStore()
    // create render function that will be called by keep
    const render = (WrappedApp: ComponentType): string => {
      return ReactDOMServer.renderToString(<WrappedApp />)
    }
    // wait for data loading and rendering app
    // you'll get HTML and initial data 
    const [html, serverDataHtml] = await serverRender(render, RegisteredApp)
    const reduxState = store.getState() // grab the initial state from our Redux store

    res.send(
      `<!doctype html>
    <html lang="">
    <head>
        ${serverDataHtml}
        <script>
          window.env = ${serialize(envConfig)};
          window.__REDUX_STATE__ = ${serialize(reduxState)};
        </script>
        ...

API

// library components
import { 
  createClientProvider,
  serverRender,
  useFetch,
  useMutate,
  reducer,
  actions,
  actionTypes,
  promiseControlSymbol
} from '@webstrop/keep'
// typescript types
import  { PromiseControl, FetchAction } from '@webstrop/keep'

Thanks

Big thanks belongs to Inventi for giving us a opportunity to develop part of this open-source package as side-effect of one secret project

Contributing

Pull requests are welcome. For major changes, please open an issue first to discuss what you would like to change.

Please make sure to update tests as appropriate.

License

MIT

Readme

Keywords

none

Package Sidebar

Install

npm i @webstrop/keep

Weekly Downloads

0

Version

1.0.12

License

MIT

Unpacked Size

40.6 kB

Total Files

16

Last publish

Collaborators

  • adambisek