Skip to content

Instantly share code, notes, and snippets.

@iddan
Last active May 18, 2017 10:27
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save iddan/6bf69a9eae2f3de451fbda75f5bad115 to your computer and use it in GitHub Desktop.
Save iddan/6bf69a9eae2f3de451fbda75f5bad115 to your computer and use it in GitHub Desktop.
New Redux
import Form from './form.jsx';
const App = (setState) => ({ entities }) => (
<div>
<h1>Entities Editor</h1>
<h2>Select an entity</h2>
<div>{
entities.map(entity => (
<div>
<h3>{ entity.id }</h3>
<Form entityId={ entity.id } />
</div>
))
}</div>
</div>
);
const initialState = {
entities: [
{
id: 'PE22',
fields: {
name: {
first: 'Iddan',
last: 'Aharonson'
}
}
},
],
};
export default connect(null, initialState)(App);
import { mapValues, reduce, set } from 'lodash/fp';
import WithPath from './with-path';
const getDispalyName = (component) => component.displayName || component.name;
const connect = (bindState, initialState = {}) => (WrappedComponentFactory) => {
return class extends React.Component {
static displayName = `Connect(${getDispalyName(WrappedComponentFactory)})`;
static contextTypes = {
state: React.PropTypes.object,
setState: React.PropTypes.func
};
static childContextTypes = {
state: React.PropTypes.object,
setState: React.PropTypes.func
}
_getState = () => {
return mapValues(WithPath, { ...bindState(this.context.state, this.props), ...initialState });
}
_setState = (newState) => {
this.context.setState(reduce(
(state, value) => set(value[WithPath.Path], value, this.context.state),
this.context.state,
{ ...newState, ...this.getState() }
));
}
getChildContext() {
return {
state: this._getState(),
setState: this._setState
};
}
render() {
const WrappedComponent = WrappedComponentFactory(this._setState);
return <WrappedComponent { ...this.props } { ...this._getState() } />;
}
};
};
import { get } from 'lodash/fp';
const Field = (setState) => ({ entity, path, label, type, value }) => (
<div>
<label>{label}</label>
<input type={ type }
value={ value }
onChange={ (e) => setState({ value: e.target.value }) } />
</div>
);
const bindState = (state, ownProps) => ({
value: get(ownProps.path, entity)
});
export default connect(bindState)(Field);
const Form = (setState) => () => (
<div>
<div>
<Field type="text" path={['name', 'first']} label="First Name" />
<Field type="text" path={['name', 'last']} label="Last Name" />
</div>
</div>
);
const bindState = (state, ownProps) => ({
entity: state.entities[ownProps.entityId]
});
export default connect(bindState)(Form);
import { connect } from 'compux';
import App from './app.jsx';
ReactDOM.render(<App />, document.querySelector('#root'));
const WithPath = (target, path = []) => new Proxy(target, {
get(target, property) {
const value = target[property];
const thisPath = [...path, property];
return {
...(typeof value !== 'object' ? value : WithPath(value, thisPath)),
[WithPath.Path]: thisPath
};
}
});
WithPath.Path = Symbol('path');
@iddan
Copy link
Author

iddan commented May 18, 2017

Known issues

  • Can't modify state without forcing update of the updating component (for example a save button in another component)

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment