I have the following react component
This would be a good use case for Refract!
The first step would be to pull the input out into a separate component:
const Input = ({ onChange, value }) => (
)
Next step would be to wrap this component with Refract's withEffects
higher-order component, with a handler
and an aperture
to handle the side-effects like this:
import { withEffects } from 'refract-rxjs'
import { debounceTime } from 'rxjs/operators'
const Input = ({ onChange, value }) => (
)
const aperture = () => component =>
component.observe('value').pipe(debounceTime(300))
const handler = ({ onUpdate }) => value => onUpdate(value)
const DebouncedInput = withEffects(handler)(aperture)(Input)
An aperture
lets you observe your component's props. In this case, it would make sense to observe the value
prop - every time the value
changes, the component.observe('value')
stream gets a new value.
The handler
is a function called with each value output by the aperture's stream. In this case, the debounced value is passed straight through to a new prop called onUpdate
.
Both apertures and handlers are explained in detail in the docs - Observing React introduces apertures, and Handling Effects explains handlers.
As an example of how you would use this:
class Search extends React.Component {
state = { debounced: '', search: '' }
onSearch = e => this.setState({ search: e.target.value })
onUpdate = debounced => this.setState({ debounced })
render() {
return (
debounced value: {debounced}
)
}
}
With this code, the text DebouncedInput
would display the user's input instantly (which is ideal for UX), while debouncing the side-effect of calling the onUpdate
callback. It would then be trivial to expose this onUpdate
to components which consume the Search
component!