renchap / webpacker-react

Webpacker plugin to integrate React in your Rails application
https://github.com/renchap/webpacker-react
MIT License
204 stars 30 forks source link

Helper to automatically load all components in a given folder #44

Open jbbarth opened 6 years ago

jbbarth commented 6 years ago

Thanks for a great gem! :)

While porting my code to webpacker-react I found it a bit tedious to "setup" every view component I have individually. I have many of them (which might not be the general case? dunno) used from different rails controllers. So I wanted to have components I use in the rails app automatically registered at pack level.

I think it's fairly common to have your react components divided into reusable components, VS "views", which are not reusable, possibly own global state via redux or alike, etc. As a result I structured my app/javascript/ folder like this:

app/javascript:
  ├── packs:
  │   └── application.js
  └── components:
  │   └── Component1.jsx
  │   └── Component2.jsx
  └── views:
  │   └── rails_controller1:
  │        └── AView1.jsx
  │        └── AnotherView2.jsx
  │   └── rails_controller2:
  │        └── AThirdView3.jsx

Now to register all views automatically, I have the following code in my pack:

import WebpackerReact from "webpacker-react"

// automatically detect all components matching ../views/**/*.jsx
// (inspired from http://code.fitness/post/2015/11/javascript-es2015-dynamic-import.html)
const components = {}
const req = require.context('../views/', true, /\.jsx$/)
const files = req.keys()
files.forEach((file) => {
  const componentId = req.resolve(file)
  const component = __webpack_require__(componentId)
  const componentName = file.match(/([^\/\\]+)\.jsx$/)[1]
  components[componentName] = component.default
})

// finally register them with webpacker-react
WebpackerReact.setup(components)

I thought it would be nice to have things handled at webpacker-react level, via something like:

import WebpackerReact from "webpacker-react"
WebpackerReact.registerAllFromDirectory("../views/", /([^\/\\]+)\.jsx$/)

What do you think? Let me know if it's not generic enough for webpacker-react, I can totally understand that ;-)

renchap commented 6 years ago

This is a very valid use-case for non-SPA applications. Feel free to submit a PR to implement this. One point to be careful about is how it interacts with hot-reloading.