Skip to content

Instantly share code, notes, and snippets.

@cahnory
Last active June 21, 2016 08:08
Show Gist options
  • Save cahnory/4953ea473f4b6d8ff19c8350d4a0af53 to your computer and use it in GitHub Desktop.
Save cahnory/4953ea473f4b6d8ff19c8350d4a0af53 to your computer and use it in GitHub Desktop.
DataSelect

Use any object as select option/value

Objects are compared with ===, object must be the same and not only deep equal

import React from 'react'
export function DataSelect({
children,
onData,
onChange,
value,
defaultValue,
...props,
}) {
const dataSet = DataSet()
// clone children with data props
const changeChildrenProps = (children) => {
return React.Children.map(children, changeChildProps)
}
// clone child with data props
const changeChildProps = (child) => {
if (child.type) {
const props = {
dataSet,
value: dataSet.getDataId(child.props.value),
defaultValue: dataSet.getDataId(child.props.defaultValue),
}
if ('option' === child.type) {
child = React.cloneElement(child, props)
} else if ('function' === typeof child.type) {
child = React.cloneElement(child, props, changeChildrenProps(child.props.children))
} else {
child = React.cloneElement(child, {}, changeChildrenProps(child.props.children))
}
}
return child
}
const handleChange = (e) => {
if (onData) {
onData(dataSet.getData(e.target.value))
}
if (onChange) {
onChange(e)
}
}
return (
<select
value={dataSet.getDataId(value)}
defaultValue={dataSet.getDataId(defaultValue)}
dataSet={dataSet}
{...props}
onChange={handleChange}
children={changeChildrenProps(children)} />
)
}
DataSelect.propTypes = {
onData: React.PropTypes.func
}
export default DataSelect
function DataSet() {
const datas = []
const dataSet = {
getDataId: (data) => {
if (undefined === data) {
return undefined
}
let key = datas.indexOf(data)
if (-1 === key) {
key = datas.length
datas.push(data)
}
return key
},
getData: (id) => {
return datas[id]
}
}
return dataSet
}
const data = [
{id: 1, name: 'foo'},
{id: 2, name: 'bar'},
]
export function Usage({value}) {
return (
<DataSelect value={value || data[0]} onData={obj => doSomething(obj)}>
{ data.map(obj => <option value={obj}>{obj.name}</option>) }
</ObjectSelect>
)
}
@lionelB
Copy link

lionelB commented Jun 21, 2016

does

<select
      value={dataSet.getDataId(value)}
      defaultValue={dataSet.getDataId(defaultValue)}
      dataSet={dataSet}
      {...props}
      onChange={handleChange}
      children={changeChildrenProps(children)} />

is the same as

<select
      value={dataSet.getDataId(value)}
      defaultValue={dataSet.getDataId(defaultValue)}
      dataSet={dataSet}
      {...props}
      onChange={handleChange}>
  {children => React.children.map(children, changeChildProp)}
</select>

@cahnory
Copy link
Author

cahnory commented Jun 21, 2016

Yes, they are exactly the same.

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