Skip to content

Instantly share code, notes, and snippets.

@gmaclennan
Created December 3, 2016 21:37
Show Gist options
  • Save gmaclennan/9f2e5f182c39fe56dbad0d0bd69d7fe2 to your computer and use it in GitHub Desktop.
Save gmaclennan/9f2e5f182c39fe56dbad0d0bd69d7fe2 to your computer and use it in GitHub Desktop.
React Drag and Drop example
const React = require('react')
const dragDrop = require('drag-drop')
const RaisedButton = require('material-ui/RaisedButton').default
const fileExtension = require('file-extension')
const blobToBuffer = require('blob-to-buffer')
const { connect } = require('react-redux')
const {replaceFeatures} = require('../action_creators')
const styles = {
wrapper: {
position: 'relative',
width: '100%',
height: '100%',
display: 'flex',
alignItems: 'center',
justifyContent: 'center',
flexDirection: 'column'
},
input: {
height: 0,
width: 0,
overflow: 'hidden'
},
text: {
margin: '1em'
}
}
class OpenFile extends React.Component {
static props = {
onData: () => {}
}
state = {
dragOver: false,
loading: false
}
update () {
this.cleanup()
this.removeDragDrop = dragDrop(this.refs['drag-drop'], {
onDrop: this.handleDrop,
onDragOver: this.handleDragOver,
onDragLeave: this.handleDragLeave
})
}
cleanup () {
this.removeDragDrop && this.removeDragDrop()
this.removeDragDrop = null
}
loadData (href) {
this.setState({loading: true, error: null})
window.fetch(href)
.then(response => response.json())
.then(this.onDataLoaded)
.catch(this.onError)
}
onDataLoaded = (data) => {
this.setState({loading: false, error: null})
this.props.onData(data.features)
}
onError = (err) => {
this.setState({error: err})
}
componentDidMount () { this.update() }
componentDidUpdate () { this.update() }
componentWillUnmount () { this.cleanup() }
handleDrop = files => {
files = files.filter(file => ['json', 'geojson'].indexOf(fileExtension(file.name)) > -1)
if (!files.length) return console.log('invalid file')
this.setState({loading: true, error: null})
blobToBuffer(files[0], (err, buf) => {
if (err) return this.onError(err)
var str = buf.toString()
try {
this.onDataLoaded(JSON.parse(str))
} catch (e) {
this.onError(e)
}
})
}
handleDragOver = () => {
clearTimeout(this.timeout)
if (this.state.dragOver) return
this.setState({dragOver: true})
}
handleDragLeave = () => {
this.timeout = setTimeout(() => this.setState({dragOver: false}), 50)
}
handleButtonClick = () => {
this.refs.fileInput.click()
}
handleFileSelection = (e) => {
this.handleDrop([this.refs.fileInput.files[0]])
}
handleSampleDataClick = (e) => {
e.preventDefault()
this.loadData(e.target.href)
}
render () {
// const dropBoxStyle = this.state.dragOver ? Object.assign({}, styles.dropBox, styles.dropBoxHover) : styles.dropBox
return (
<div style={styles.wrapper} ref='drag-drop'>
<div style={styles.input}>
<input type='file' ref='fileInput' onChange={this.handleFileSelection} />
</div>
{this.state.loading && <div>Loading</div>}
<RaisedButton label='Select a file' primary onClick={this.handleButtonClick} />
<div style={styles.text}>
or explore some <a href='sample.geojson' onClick={this.handleSampleDataClick}>sample data</a>
</div>
</div>
)
}
}
module.exports = connect(
null,
(dispatch) => ({onData: features => dispatch(replaceFeatures(features))})
)(OpenFile)
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment