Last active
August 23, 2017 14:58
-
-
Save dtothefp/1a10f300749960ba64c50ce4eceec458 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// HOC and context | |
// provide context with HOC | |
import App from './components/App'; | |
import ProvideContext from './containers/ProvideContext'; | |
const transportationTypes = [ | |
'armored car', | |
'fire engine', | |
'golf cart', | |
'hyperloop' | |
]; | |
const elm = document.getElementById('app'); | |
const Component = ( | |
<ProvideContext types={transportationTypes}> | |
<App /> | |
</ProvideContext> | |
); | |
render(Component, elm); | |
// receive context with HOC | |
import TypeListItem from './TypeListItem'; | |
import contextToProps from '../containers/contextToProps'; | |
class TransportationList extends Component { | |
render() { | |
return ( | |
<ul> | |
{this.props.types.map((type, i) => ( | |
<TypeListItem | |
key={`type_${i}`} | |
type={type} | |
/> | |
))} | |
</ul> | |
); | |
} | |
} | |
const propTypes = { | |
types: PropTypes.array.isRequired | |
}; | |
TransportationList.propTypes = propTypes; | |
export default contextToProps(TransportationList, propTypes); | |
// provide context container | |
import {Children, Component} from 'react'; | |
import PropTypes from 'prop-types'; | |
class ProvideContext extends Component { | |
getChildContext() { | |
return {types: this.props.types}; | |
} | |
render() { | |
return Children.only(this.props.children); | |
} | |
} | |
ProvideContext.propTypes = { | |
types: PropTypes.array.isRequired, | |
children: PropTypes.element.isRequired | |
}; | |
ProvideContext.childContextTypes = { | |
types: PropTypes.array.isRequired | |
}; | |
export default ProvideContext; | |
// HOC to receive context | |
import {createElement, Component} from 'react'; | |
import hoistNonReactStatics from 'hoist-non-react-statics'; | |
export default function(ChildComponent, dataBindings) { | |
class ContextToProps extends Component { | |
render() { | |
const mergedProps = Object.assign( | |
{}, | |
this.state, | |
this.context, | |
this.props | |
); | |
return createElement(ChildComponent, mergedProps); | |
} | |
} | |
ContextToProps.contextTypes = dataBindings; | |
hoistNonReactStatics(ContextToProps, ChildComponent); | |
return ContextToProps; | |
} | |
// setting state and using forms | |
import FormFilter from './FormFilter'; | |
import TypeList from './TypeList'; | |
class App extends Component { | |
constructor(props) { | |
super(props); | |
this.state = { | |
types: props.types, | |
value: '' | |
}; | |
this.filterTypes = this.filterTypes.bind(this); | |
} | |
filterTypes(value) { | |
const {types} = this.props; | |
const filterVal = value.toLowerCase(); | |
const matchedTypes = types.filter(type => { | |
return type.toLowerCase().startsWith(filterVal); | |
}); | |
this.setState({ | |
types: matchedTypes, | |
value | |
}); | |
} | |
render() { | |
const {types, value} = this.state; | |
return ( | |
<div className="container"> | |
<div className="row"> | |
<FormFilter | |
handleChange={this.filterTypes} | |
value={value} | |
/> | |
<TypeList types={types}/> | |
</div> | |
</div> | |
); | |
} | |
} | |
export default App; | |
// bootstrap | |
import App from './components/App'; | |
const elm = document.getElementById('app'); | |
const transportationTypes = [ | |
'armored car', | |
'fire engine', | |
'golf cart', | |
'hyperloop' | |
]; | |
render( | |
<App | |
types={transportationTypes} | |
/>, | |
elm | |
); | |
// form filter | |
import React from 'react'; | |
import PropTypes from 'prop-types'; | |
const FormFilter = ({ | |
handleChange, | |
value | |
}) => { | |
return ( | |
<div className="col"> | |
<form> | |
<input | |
type="text" | |
name="filter" | |
placeholder="Filter Types" | |
value={value} | |
onChange={e => handleChange(e.target.value)} | |
/> | |
</form> | |
</div> | |
); | |
}; | |
FormFilter.propTypes = { | |
handleChange: PropTypes.func.isRequired, | |
value: PropTypes.string.isRequired | |
}; | |
export default FormFilter; | |
// local styles | |
import cx from 'classnames'; | |
import styles from './ListStyles.scss'; | |
const TypeListItem = (props) => { | |
const {type, index} = props; | |
const styleKey = index % 2 === 0 ? 'even' : 'odd'; | |
const className = cx(styles[styleKey], { | |
active: type === 'hyperloop' | |
}); | |
return <li className={className}>{type}</li>; | |
}; | |
TypeListItem.propTypes = { | |
index: PropTypes.number.isRequired, | |
type: PropTypes.string.isRequired | |
}; | |
export default TypeListItem; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment