injectSaga.tsx 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465
  1. import React from 'react'
  2. import hoistNonReactStatics from 'hoist-non-react-statics'
  3. import { ReactReduxContext } from 'react-redux'
  4. import getInjectors from './sagaInjectors'
  5. /**
  6. * Dynamically injects a saga, passes component's props as saga arguments
  7. *
  8. * @param {string} key A key of the saga
  9. * @param {function} saga A root saga that will be injected
  10. * @param {string} [mode] By default (constants.DAEMON) the saga will be started
  11. * on component mount and never canceled or started again. Another two options:
  12. * - constants.RESTART_ON_REMOUNT — the saga will be started on component mount and
  13. * cancelled with `task.cancel()` on component unmount for improved performance,
  14. * - constants.ONCE_TILL_UNMOUNT — behaves like 'RESTART_ON_REMOUNT' but never runs it again.
  15. *
  16. */
  17. export default (descriptor: { key: string, saga: any, mode?: string }) => (WrappedComponent) => {
  18. const { key, saga, mode } = descriptor
  19. class InjectSaga extends React.Component {
  20. public static WrappedComponent = WrappedComponent
  21. public static contextType = ReactReduxContext
  22. public static displayName = `withSaga(${WrappedComponent.displayName ||
  23. WrappedComponent.name ||
  24. 'Component'})`
  25. private injectors = null
  26. constructor (props, context) {
  27. super(props, context)
  28. this.injectors = getInjectors(context.store)
  29. this.injectors.injectSaga(key, { saga, mode }, this.props)
  30. }
  31. public componentWillUnmount () {
  32. this.injectors.ejectSaga(key)
  33. }
  34. public render () {
  35. return <WrappedComponent {...this.props} />
  36. }
  37. }
  38. return hoistNonReactStatics(InjectSaga, WrappedComponent)
  39. }
  40. const useInjectSaga = (descriptor: { key: string, saga: any, mode?: string }) => {
  41. const { key, saga, mode } = descriptor
  42. const context = React.useContext(ReactReduxContext)
  43. React.useEffect(() => {
  44. const injectors = getInjectors(context.store)
  45. injectors.injectSaga(key, { saga, mode })
  46. return () => {
  47. injectors.ejectSaga(key)
  48. }
  49. }, [])
  50. }
  51. export { useInjectSaga }