0.4.1 • Published 6 years ago

@rognstadragnar/contextual v0.4.1

Weekly downloads
1
License
MIT
Repository
github
Last release
6 years ago

Installation

npm i @rognstadragnar/contextual

Basic usage

Step 1: Create Provider components

They must wrap whatever wants to consume their state and actions.

import { h, Component } from 'preact'
import { Provider } from '@rognstadragnar/contextual'
import { Something } from './somwhere'

export class CounterContainer extends Component {
  state = {
    count: 0
  }
  increment = todo => {
    const count = this.state.count + 1
    this.setState({ count })
  }
  decrement = todo => {
    const count = this.state.count - 1
    this.setState({ count })
  }
  render() {
    return (
      <Provider
        name="counter-state"
        state={{ count: this.state.count }}
        actions={{
          increment: this.increment,
          decrement: this.decrement
        }}
      >
        <Something />
      </Provider>
    )
  }
}

Step 2: Create <Consumer /> components

They can be used anywhere in your component tree as long as the <Provider /> they consume wraps them.

State and actions from the <Provider /> can be leveraged in ceveral ways:

  1. Functions that return components
  2. Components injected with state and actions
  3. TODO: Render property
  4. TODO: Consume/connect wrapper functions like react-redux

1. Functions as consumer children

import { h, Component } from 'preact'
import { Consumer } from '@rognstadragnar/contextual'

const SomeComponent = ({ count, increment, decrement }) => {
  return (
    <main>
      <h1>{count}</h1>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </main>
  )
}

export const Something = () => {
  return (
    <Consumer consumes="counter-state">
      {(state, actions) => (
        <SomeComponent
          count={state.count}
          increment={actions.increment}
          decrement={actions.decrement}
        />
      )}
    </Consumer>
  )
}

2. Components with injectable props as consumer children

import { h, Component } from 'preact'
import { Consumer } from '@rognstadragnar/contextual'

const SomeComponent = ({ state, actions }) => {
  return (
    <main>
      <h1>{state.count}</h1>
      <button onClick={actions.increment}>Increment</button>
      <button onClick={actions.decrement}>Decrement</button>
    </main>
  )
}

export const Something = () => {
  return (
    <Consumer consumes="counter-state">
      <MyComponent />
    </Consumer>
  )
}

3. TODO: Render property

import { h, Component } from 'preact'
import { Consumer } from '@rognstadragnar/contextual'

const SomeComponent = ({ count, increment, decrement }) => {
  return (
    <main>
      <h1>{count}</h1>
      <button onClick={increment}>Increment</button>
      <button onClick={decrement}>Decrement</button>
    </main>
  )
}

export const Something = () => {
  return (
    <Consumer
      consumes="counter-state"
      render={(state, actions) => (
        <SomeComponent
          count={state.count}
          increment={actions.increment}
          decrement={actions.decrement}
        />
      )}
      // or like this, similiar to #3
      render={<SomeComponent />}
    />
  )
}

4. TODO: React-redux inspired consume/connect function

import { h, Component } from 'preact'
import { Consumer } from '@rognstadragnar/contextual'

const MyComponent = ({ state, actions }) => {
  return (
    <main>
      <h1>{state.count}</h1>
      <button onClick={actions.increment}>Increment</button>
      <button onClick={actions.decrement}>Decrement</button>
    </main>
  )
}

export const Something = consume({ consumes: 'counter-state' })(MyComponent)

Properties

<Provider />

PropertyTypeDescriptionRequired
namestringidentifier used if multiple <Provider /> in one app Yes, if using more than one <Provider />
stateanyState available to consumers throughout the appNo
actionsanyActions available throughout the appNo

<Consumer />

PropertyTypeDescriptionRequired
consumesstring or string[]Which <Provider /> it consumesYes
children (regular)Component<{state, actions}> or (state, actions) => Component<{state, actions}>The children of the <Consumer />Yes
TODO: renderComponent<{state, actions}> or (state, actions) => Component<{state, actions}>Instead of chidrenNo
mapStateToPropsnull or (state) => anyExtract or transform the state provided to the consumerNo
mapActionsToPropsnull or (actions, state) => anyExtract or transform the actions provided to the consumerNo
fragmentComponent or (children) => ComponentWraps the children. Default: nothing or <span /> if children.length > 2No

Note:

  1. If using either mapStateToProps, mapActionsToProps or both, props will be flattened like so { ...state, ...actions, ...rest }
  2. If consumes is an array of strings (e.g. <Consumer consumes={['a', 'b']} />, each will be object properties of the state and actions (e.g. { a: ..., b: ... })

Examples

License

MIT.

0.4.1

6 years ago

0.4.0

6 years ago

0.3.2

6 years ago

0.3.1

6 years ago

0.3.0

6 years ago

0.1.0

6 years ago

0.0.1

6 years ago