-
Notifications
You must be signed in to change notification settings - Fork 3
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Provide method to debounce changes #4
Comments
The debounce property should live on the NamespaceComponent instance rather than as a per field specification. For completeness sake a method to bypass the debounce and commit the changes should be provided. |
A first pass implementation required field locks to mediate events when multiple fields were edited within the delta. import React, { Component, PropTypes } from 'react';
import * as ReactRedux from 'react-redux';
import find from 'lodash.find';
import isFunction from 'lodash.isFunction';
import result from 'lodash.result';
import isString from 'lodash/isString';
import flow from 'lodash/flow';
import debounce from 'lodash/debounce';
import identity from 'lodash/identity';
export const BIND = 'BIND_NAMESPACE';
export const shape = {
assign: PropTypes.func.isRequired,
dispatch: PropTypes.func.isRequired,
select: PropTypes.func.isRequired
}
export function assign(namespace, key, value) {
if (! key)
return (key, value) =>
assign(namespace, key, value);
let action = (value) => ({
type: BIND, payload: { namespace, key, value } })
if ([...arguments].length < assign.length)
return action;
return action(value);
}
function selectWith (selector, value) {
if (arguments.length === 1) {
return selectWith.bind(null, selector);
}
return (
isString(selector) ? result(value, selector)
: isFunction(selector) ? selector(value)
: value
)
}
export function connect(namespace, initial={}) {
return (WrappedComponent) =>
ReactRedux.connect(
({ namespace: { [namespace]: state } }) => ({
assign: assign(namespace),
select(key, __) {
return arguments.length > 0 ? result(state, key, __) : state || {}
}
})
)(class NamespaceBridge extends Component {
constructor() {
super(...arguments);
// retains debounced values
this.state = {};
this.debounced = {};
}
componentWillReceiveProps(props) {
let newState = {};
Object.keys(this.state).map((key) =>
newState[key] = props[key])
this.setState(newState);
}
render () {
let {assign, dispatch, select, ...props} = this.props;
function dispatcher(target, value) {
return (
// curry or assign many
arguments.length === 1 ?
// curry assign with target
isString(target) ?
dispatcher.bind(this, target)
// map target ({key: value}) => assign
: ( Object.keys(target).map((key) =>
dispatcher(key, target[key]))
, target )
// deferred selector
: isFunction(value) ?
(...args) => dispatcher(target, value(...args))
// memoize
: select(target) !== value ?
( dispatch(assign(target, value))
, value )
: value
)
}
props = {
// namespace defers to props
...select(),
...props,
assign: dispatcher,
assigns(key, selector) {
return dispatcher(key, selectWith(selector))
},
debounces: (key, selector, timeout) => {
if (key && ! selector) {
return result(this.state, key, props.select(key));
}
this.debounced[key] = this.debounced[key] || {
timeout,
bouncer: debounce(dispatcher(key), timeout)
}
return (value) => {
value = selectWith(selector, value);
this.debounced[key].bouncer(value);
this.setState({ [key]: value });
}
},
dispatch,
select,
selects() {
return select.bind(null, ...arguments);
},
touched(key) {
return select(['@@touched'].concat(key), false);
}
}
return React.isValidElement(WrappedComponent) ?
React.cloneElement(WrappedComponent, props) : <WrappedComponent {...props}/>
}
})
}
export function reducer (state={}, action={}) {
if (action.type === BIND) {
let { payload: { namespace, key, value } } = action
let ns = result(state, namespace, {});
let touched = result(ns, '@@touched', {});
ns = {
...ns, [key]: value, ['@@touched']: { ...touched, [key]: true } };
state = { ...state, [namespace]: ns };
}
return state;
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Provide a method to debounce changes to assigned fields
returns a referentially transparent function keyed off method name that is consistent across renders.
The text was updated successfully, but these errors were encountered: