I'd like to load a react js component dynamically through an html file input. Essentially, I'd like to achieve the same effect as if I had done import Foo from ./foo.js
I can read the file as text after the onChange event of the html element, but then I don't know what to do with it? Is it even possible to achieve my goal? Thanks!
onChange(e) {
var fr = new FileReader()
fr.addEventListener('load', f => {
window.console.log(f.target.result.substring(0, 500))
// yields: import React, { Component } from 'react' ... class Foo extends Component { ...
// but now what?
})
fr.readAsText(e.target.files[0])
}
So, I ended up getting this to work with babel-standalone. I'm only able to use stateless, functional components, however, and I feel as though my implementation could be improved. For example, I don't like how I have to string.prototype.replace
.
Anyway, here's what worked for me, hopefully it might help you, too.
// fileToBeLoaded.js
const elem = () => <h1>Hello, world!</h1>
// foo.js
import React, { Component } from 'react'
import { transform } from 'babel-standalone'
class Foo extends Component {
constructor(props) {
super(props)
this.state = {
elem: undefined
}
this.handleChange = this.handleChange.bind(this)
}
handleChange(e) {
let fr = new FileReader()
fr.addEventListener('load', e1 => {
let s = e1.target.result
let result = transform(s, {
presets: ['es2015'],
plugins: ['transform-react-jsx']
})
let s1 = result.replace(`'use strict';
let elem = function elem(props) {`, 'elem = function(props) {')
let elem = () => {}
elem = eval(s1)
this.setState({elem})
})
fr.readAsText(e.target.files[0])
}
render() {
const Elem = this.state.elem ? this.state.elem : () => <h1>No elem!</h1>
return (
<div>
<input type="file" onChange={this.handleChange}
<Elem />
</div>
)
}
}
Collected from the Internet
Please contact [email protected] to delete if infringement.
Comments