Refract
  • Read Me
  • Introduction
    • Why Refract?
    • Core Concepts
    • Thinking In Refract
    • Alternatives
  • Usage
    • Getting Started
    • Installation
    • Connecting To React
    • Observing React, Preact and Inferno
    • Injecting Dependencies
    • Observing Redux
    • Observing Anything
    • Handling Effects
    • Pushing to Props
    • Rendering Components
    • Handling Errors
    • Testing
  • Recipes
    • Dependency Injection
    • Creating An API Dependency
    • Handling state
    • Replacing Redux Connect
  • Examples
    • Debounced fetch
    • Counter
    • Field validation
    • Redux fetch
    • Routing
    • Typeahead
    • Visit time
  • API
    • compose
    • withEffects
    • toProps, asProps
    • useRefract
    • refractEnhancer (Redux)
  • Glossary
  • Feedback
Powered by GitBook
On this page
  • Adding Props
  • Replacing Props
  • Stateful Apertures
  1. Usage

Pushing to Props

PreviousHandling EffectsNextRendering Components

Last updated 6 years ago

By now, you should have a better understanding of what Refract does:

  • It allows you to observe data sources (, , )

  • It allows you to push data to an effect handler (see )

Refract has three built-in effect handlers, to:

  • Pass additional props to the child it wraps

  • Replace props

  • Render components

This section focuses on adding and replacing props, and its applications. All React, Preact and Inferno packages export two effect creators: toProps and asProps. They both take an object of props.

Note that by default, props passed to toProps and asProps won't be merged with previous values: to enable this behaviour, you need to set mergeProps to true in withEffects config.

Adding Props

Any value emitted by your aperture which has been wrapped with toProps will cause the wrapped component to re-render with the additional provided props. Let's see a very simple example where a prop doubledValue is computed from a prop value:

import React from 'react'
import { withEffects, toProps } from 'refract-rxjs'
import { map } from 'rxjs/operators'

const DoubleValue = ({ value, doubledValue }) => (
    <div>Two times {value} is {doubledValue}</button>
)

const aperture = (component, { initialCount }) => {
    component.observe('value').pipe(map(value => toProps({
        doubledValue: 2 * value
    })))
}

export default withEffects(aperture)(DoubleValue)

Replacing Props

asProps is used exactly like toProps, except that the provided props will be the only ones passed to the child component.

It allows you to fully control what props are passed through, and can result in performance benefits by controlling exactly when a component re-renders.

Essentially, toProps and asProps allow you to inject data into components, by using existing props or external data sources (sideways data loading).

Stateful Apertures

With the ability to set component props and to listen to events (with pushEvent and component.fromEvent(name)), comes the ability to handle state: events are the source of truth, and state is a projection of these events.

Note the use of component.useEvent(eventName) which returns a tuple containing the result of fromEvent(eventName) and pushEvent(eventName) (and the use of startWith to ensure the addOne prop is passed to the component on initial render).

import React from 'react'
import { withEffects, toProps } from 'refract-rxjs'
import { scan, startWith, map } from 'rxjs/operators'

const Counter = ({ count, addOne }) => <button onClick={addOne}>{count}</button>

const aperture = (component, { initialCount }) => {
    const [addOneEvents$, addOne] = component.useEvent('addOne')

    return addOneEvents$.pipe(
        startWith({
            count: initialCount,
            addOne
        }),
        scan(({ count, ...props }) => ({
            ...props,
            count: count + 1
        })),
        map(toProps)
    )
}

export default withEffects(aperture)(Counter)

The example below is a simple counter example: each time a button is clicked, the count is incremented. We use a reducer to persist state between events, and pass it as props. It will sound familiar if you've used Redux: we go from events to state to props, the same way Redux (with connect) goes from actions to state to props (see recipe). Refract can be used to bind together state from multiple sources.

React
redux
anything else
handling effects
Replacing react-redux connect HoC