-
Notifications
You must be signed in to change notification settings - Fork 24.3k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Require file dynamically by variable #6391
Comments
Based on how the packager works, this isn't really possible with require. You can do something like this though:
|
What if I'd like to require all files in dir? |
You could also create a single file that just serves to require all of the needed components into an object and then exports that object. Then all you need to do is require that single file.
|
Thanks @rxb, I know I can collect my components in many ways. I appreciate your help, but I'd like to know if there is any way to require file with dynamic string path or require all files in dir without knowing what are they. |
This is not possible -- you should generate a massive switch-case statement that looks like this:
|
You have to think of how this code will execute within a production app -- all assets must be present the way React Native is configured out of the box. Does this issue need to stay open? |
@facebook-github-bot stack-overflow |
Hey @adampietrasiak and thanks for posting this! @jsierles tells me this issue looks like a question that would be best asked on StackOverflow. StackOverflow is amazing for Q&A: it has a reputation system, voting, the ability to mark a question as answered. Because of the reputation system it is likely the community will see and answer your question there. This also helps us use the GitHub bug tracker for bugs only. Will close this as this is really a question that should be asked on SO. |
The inability to require modules programatically (as opposed to statically) is extremely limiting. There are new language constructs coming like import() which makes this mandatory in any JS environments, React Native simply cannot afford this simplistic approach. And the frustrating thing is the support is almost there, its just limited to development environment. |
I suspect React Native will support async function getDataAsync() {
const ApiClient = await import('./ApiClient').default;
return await ApiClient.getDataAsync();
} Perhaps Metro bundler will have a way to support semi-dynamic imports if you give it a list of files that may possibly be included up front: function unusedThisIsJustForBundling() {
import('./ApiClient');
}
async function getDataAsync(apiClientModuleName) {
const ApiClient = await import(apiClientModuleName).default;
return await ApiClient.getDataAsync();
}
getDataAsync('./ApiClient') If you have a constructive idea that works well in React Native while meeting its constraints, please suggest it. |
hey @ide Thanks for your reply. Let me explain why I think it is important to be able to import a module without directly referencing it (using a string literal). I recently started to use a dependency injection framework (appolo-inject) and there you can describe how your objects are wired together, etc. The framework uses require() to load the modules just in time, which is quite nice, given you can have a large dependency graph, which do not want to load in one go. But for this to work, you need to be able to pass a variable to the require() call. And if you think about it in general, being constrained to use string literals only does feel very limiting, I mean you are stripped from the ability to make runtime, dynamic decisions on module loading. By the way import() specification (see https://github.com/tc39/proposal-dynamic-import) describes the ability to support runtime determined strings (aka variables) for import, so I am not sure if the above described approaches would be satisfactory. Also the current situation is rather inconsistent, these constructs work fine in Jest tests, and yet they fail when running the actual code. I do not think redefining (constraining) require() this way is a good approach. Since this is working in development environment, could this not be allowed to work in production builds? Here is what I am referring to:
So it is possible to do a reverse lookup to get a module id in development, I do not quite see why this should not be allowed in production? |
Any thoughts anyone? |
A couple of things -
|
Ok I think the core problem boils down to how to communicate it to the packager that you may want to import something at runtime, as we want the packager to bundle all resources that can potentially be requested (require()-d or import()-ed) at runtime. The problem is that I think the packager (just like webpack) scans the imports and builds a dependency tree, and so if something is not literally and statically imported, it will be missed by the packager. I can think of an easy way out of this. Since we cannot rely on the code here, we need to add this information in the configuration. Just like we use aliases, we could have configuration for dynamic ('potential') imports. I suggest the ability to mark whole folders as potentially required. The files in those folders would be added to the bundle even if they're not explicitly required by static means. Thoughts? |
+1 for this. As stated further above there are workarounds like building a gigantic switch statement, but that seems incredibly brittle and unmanageable. Since for now this seems like an edge issue would it possible to support this functionality with a flag to the react-native cli? Maybe a "dynamicImports" folder as a sort of catch al?l |
@pie6k So are you saying that just because certain tools or libraries cannot support something we need to abandon it? This doesn't sound like a valid argument to me. The JavaScript language will very soon have import() with full dynamism. React Native will feel very old school at that point. As I pointed out above, there are a number of use cases (especially lower level framework code, that true) where such dynamic ability to require module is a must. |
@averypfeiffer I'd rather have an ability to explicitly mark modules/folders as dynamically importable. It would result in healthier code organisation, etc. |
@jarecsni I agree, just trying to think of the simplest path forward while import() is still in the proposal stage. Another possibility would be adding a "special comment" syntax similar to what flow does with |
Guys, do you think anything will happen around this any time soon? Do I need to raise this somewhere else as a feature request maybe? I mean I do think it is important and would like to follow it through and maybe contribute if I can, just a bit unsure as to how. Thanks. |
@jarecsni I don't think it's a priority right now. The repo to continue this conversation on is https://github.com/facebook/metro-bundler. |
Is there an issue in the metro-bundler repo to keep tabs on this? I am relatively new to RN and had thought to use dynamic require() calls to solve my particular use case but suppose I'll need an alternate solution in the short term. |
Opened facebook/metro#52 |
You can do this with It works for us in production. |
@serhiipalash Thanks a lot! |
@episodeyang np Be aware that if you import modules in this way, bundler will not know about new files added in folder after it started. You have to restart bundler each time you add new files in imported folder. It is important only in development when you create new files. |
I had a hard time getting
To do the loading of JSON files:
|
You can use eval |
I find it odd that people are saying this is impossible, when Webpack does it and has for a long, long time: https://webpack.js.org/guides/dependency-management/#require-with-expression |
I want to require files like:
var component = require("myApp/components/" + name);
Seems like require wants passed string to be static, not dependent on any runtime actions.
Is there any way to require files by dynamic string?
Here is similar question, but based on node.js
The text was updated successfully, but these errors were encountered: