Is there support for adding in environment variables like create-react-app allows? I tried it the way I usually do and it didn't work, but not sure if there is something in expo that allows it.
We can definitely look at adding some. Which environment variables were you trying to set?
Would love that, too. I'm trying to switch between two possible entry points (namely the real app and https://github.com/storybooks/react-native-storybook). Currently, I work around this issue by commenting out the respective component in App.js. IMHO, it would be much cleaner if I could set an environment variable in my npm tasks and choose the component depending on that, though.
We use environment variables a lot when we build so that we don't have to hardcode things like REST endpoints.
Also looking for this. My use case is that I need a url that leads to my host machine where I have an api server running. I would then like to be able do something like
API_HOST=http://$(ipconfig getifaddr en0):4000 npm start. Perhaps there's a better solution?
I believe Create React App just exposes any variables that start with REACT_APP. I figured this would just work the same.
Thanks for the input everyone! I think we have a plan to implement this, I'll post here with updates.
Update: the path to implementing this is a little trickier than I initially thought. Specifically, it's difficult to support this in a way that will continue to work after ejecting. Keeping this open so that it's still on our radar, but it might take a little while to figure out the right way to do implement.
Thanks for the update, @dikaiosune! Quick and silly question -- with "vanilla" React Native, I simply would use babel-plugin-transform-inline-environment-variables in my .babelrc to handle this. I see that this won't work for CRNA/Expo, as I modified my CRNA .babelrc like so:
{
"presets": ["babel-preset-expo"],
"plugins": ["transform-inline-environment-variables"],
"env": {
"development": {
"plugins": ["transform-react-jsx-source"]
}
}
}
I'm just curious as to how/where the Babel transformations of our CRNA/Expo code occur? I assumed that the Packager would pick up the .babelrc on my project's root, but that doesn't appear to be the case. I tried reading through the source but couldn't find the answer.
My best guess is that the Babel transforms occur right on the Expo Client itself, or the Packager has its own Babel config that is not overridable?
@ericnograles I don't see why that wouldn't work in principle -- can you upload a minimal repro project somewhere so that I can try?
Sorry for the delay, @dikaiosune, here's a sample repo: https://github.com/ericnograles/crna-sample-env-variables
You'll notice my .babelrc has the line for transform-inline-environment-variables. Basically, I have a value in /common/constants.js that should resolve to the ENVIRONMENT_CURRENT environment variable, but defaults to Dangit it didn't work! if the swap doesn't happen.
I set the environment variable like so and run yarn start

Also, I tried setting the environment variable as part of the start script like below:
"start": "ENVIRONMENT_CURRENT=YO react-native-scripts start",
And still no luck. I don't _think_ I'm doing anything silly here, but you be the judge. Let me know if that's enough info to go by.
Thanks for your help!
@dikaiosune so I'm an idiot. I completely forgot that the CRA process ignores all env variables that didn't start with REACT_ and looks like you guys applied the same thing, except you expect a REACT_NATIVE_ to start after I rtfm in the Environment Variables section 馃ぃ
So, it works, huzzah!
TL;DR: For anybody following my thread, you can do this via the start script like so:
"start": "REACT_NATIVE_ENVIRONMENT_CURRENT=YO react-native-scripts start",
And it works! Be sure to set environment variables to start with REACT_NATIVE_ or it will be ignored, similar to how environment variables that don't start with REACT_ are ignored by CRA.
Note: You don't actually need to add the babel-plugin-transform-inline-environment-variables plugin above, it seems to work fine without it.
Update: Got a PR out to address the documentation gap. Hope it helps someone! https://github.com/react-community/create-react-native-app/pull/125
@ericnograles you're right! I left a comment on the PR, but for the benefit of anyone who finds this thread:
As of today (3/28/17), the functionality @ericnograles described above only works in development mode within CRNA -- if you eject or publish to Expo then your code will no longer see the environment variables. Please treat this feature as experimental until we can work out ejection support and provide stable documentation.
@ericnograles @dikaiosune
Many people like me want to store environment variables in .env file instead of passing on command line or package.json. May you give us the proper way to do it.
I have tried package like zoo , react-native-config but not working.
@nsisodiya - can you explain why you would like to store config for a client app in a .env file rather than a json file? As far as I can tell the only difference is that you use a different parser to load the config file. It's not like you deploy to production and then suddenly you have some server environment where your env vars are already set and available, you still need to deploy your config with your app. I'm genuinely confused.
@brentvatne I am fine with storing variable in JSON file too.
you mean, I should store in .env.json file and do
import Config from '.env.json' in js files?
I do not want to put env variable in package.json. That is my main concern !!
Also, I want to keep .env or .env.json file as git-ignored file.
You could just call it config.json or something, no need for .env. And then just add that to your gitignore. import Config from './config.json'
@brentvatne @dikaiosune - My biggest pain right now is, Do I need to commit this config.json or not ?
I do not want to commit this because this config.json has Server API url. now this server API url changes while development.
CAse 1 - If I do not commit this config.json file, and put in gitignore then - everybody will be able to write their local API server path, but in this case, I do not know if this uncommited and gitignored file will be picked while publishing standalone app build. I am using expo.
Case 2 - If I commit this config.json file, then everybody will have to overwrite this file and by they by mistake commit this file with path of local environment.
====
I am unable to get a differentiating factor where I can decide whether this app is working at my local dev environment or in published environment so that I can choose right API server.
CAse 1 - If I do not commit this config.json file, and put in gitignore then - everybody will be able to write their local API server path, but in this case, I do not know if this uncommited and gitignored file will be picked while publishing standalone app build. I am using expo.
yes, it will be picked up when publishing, Expo has nothing to do with git or gitignores
Case 2 - If I commit this config.json file, then everybody will have to overwrite this file and by they by mistake commit this file with path of local environment
it's common practice to commit something like config.json.example and then explain in the project README under a setup section that you need to copy that and call it config.json and add your secrets to it
Hey, I'd like to inject the build date / build version / git commit hash and things like that as variables of my app. What's the best way to do that? It should work for dev and prod.
@nsisodiya If you insist on using a .env file, then react-native-dotenv might come in handy. @brentvatne's suggestion is probably the way to go though.
@slorber - so this isn't really related to Create React Native App, it's more of an Expo thing, but Expo gives you 1) build date 2) a revisionId for every build, which is unique and we generate for you 3) the version that you put in app.json/exp.json. You can access these through Expo.Constants.manifest -- 1) publishedTime 2) revisionId 3) version.
As for a commit hash -- you'd need to add that somewhere in your app.json/exp.json (under the extra key) or drop it into a js file before publishing.
Thanks this will solve my usecase, but it would be nice to have a flexible option where we can compute with JS the vars to inject. It can become a bit messy to modify/revert the exp.json file on every publish
@slorber - it sounds like what you want is some kind of prePublish hook where you can add metadata to the extra field in exp.json at the time of publishing?
yes it probably works but exp.json is versionned and I don't necessarily want to persist this change
For @slorber and anyone else who may find this useful, this is how I have resolved to handle not tracking my environment variables but still generating an app.json file from a tracked configuration source. Feedback welcome!
https://gist.github.com/joelbowen/1d2f2dfa471efad2154e6318c195b77e
TL;DR I create a base-app.json that is the configuration source, and a .env file that has environment variable declarations. Then I untrack both .env and app.json files and generate app.json before the important scripts run.
To anyone who has scrolled down here still having issues with environment variables for different scripts. I have made a solution that worked for myself for React Native
"react": "16.2.0",
"react-native": "0.52.0",
"babel-plugin-transform-inline-environment-variables": "0.3.0",
Following @ericnograles solution
"scripts": {
"start-a": "REACT_NATIVE_A=X react-native start --reset-cache",
"start-b": "REACT_NATIVE_A=Y react-native start --reset-cache",
...
}
// variable.js
export const VARIABLE = process.env.REACT_NATIVE_A;
I had to add --reset-cache because when running a different script it would still have the previous scripts variable if the file variable.js did not change. Using --reset-cache removed everything so it takes a minute to reload everything again but at least it works.
Use babel transform-inline-environment-variables plugin.
If you don't want to add --reset-cache in your package.json. You can also run this by doing
npm run start-a -- --reset-cache
https://github.com/facebook/react-native/issues/1924#issuecomment-251215132
@SrdjanCosicPrica are you using CRNA by any chance?
@fatahn Yes and it is ejected. Any reason why you ask?
I'm just leaving this here for people to not ruin their night when trying to get the basic .env work in an _un-ejected_ CRNA app. React Native actually passes any environment variable prefixed with REACT_NATIVE_, just like web. But these variables have to be loaded in the process running CRNA. There is a way to actually achieve this.
First, you have to choose a library that can parse the .env file. I chose the dotenv package because it can load the file by simply including a module. Now, we have to load this module before CRNA actually starts. After searching the internet I found out that Node has an -r option (to require a module) and NPX has an -n option (to pass an option to node). These two combined can load the dotenv module in the same process as an executable node binary.
Combining these methods, .env parser, node cli require module and npx pass node option, we can setup our scripts similar to this.
// package.json
{
"scripts": {
"start": "npx -n='-r dotenv/config' react-native-scripts start",
"test": "node -r dotenv/config node_modules/jest/bin/jest.js"
}
}
It might not be the best solution, but this works in the current environment when starting CRNA from cli (not Expo XDE). I also have no clue what happens when creating an Android or iOS standalone app. But if you are looking for a working .env without including it in actual project code, this is _a way_ to do that...
Just use https://github.com/luggit/react-native-config
I use it for my published applications. It allows to use variables from .env file even in Java and Swift code.
@NachtRitter As much as I like how it's supposed to work, it still doesn't work for non-ejected expo apps. I really don't want to eject as it will become harder to maintain it myself. If only there was a way to use luggit without ejecting! 馃槩
@byCedric Can you show how you access your .env variables in your code after setting things up with NPX and dotenv?
I was able to get it working, I had to fully restart Expo so that it would reload my .env file and now I can access environment variables with process.env.REACT_NATIVE_BASE_URL.
The hot reloading doesn't reload the .env file though so after the first run my environment variable go away. Haven't found a solution for that yet, but thanks @byCedric!
Hey guys,
So, I ended up using react-native-dotenv for my CI needs and local dev, and it works like a charm. So, assuming you have setup a CI provider of your choice (Circle, Travis, Codeship, GitLab, BB, Heroku, whatever), I took the following steps
.env to the .gitignoreprintenv > .env at the root of the repoexp hence the yarn run's)# Login to expo
yarn run exp login -u $EXP_USERNAME -p $EXP_PASSWORD
# Deploy to the right release channel
yarn run exp publish --release-channel $EXP_RELEASE_CHANNEL
...of course, assuming I've defined the env vars defined above.
Anyway, it works great, and I've got auto publishes to the various release channels I've got defined.
For my local developers, I just have a standard .env file stored off in a Google Drive that I share for any new dev that I onboard to my project -- i.e. I have them download it and save it to the root of their local repo. Since it's ignored, the SCM stays clean.
@ericnograles You might want to add a .env.example containing the names (not values) for all existing environment variables. You can commit that one to the repo and maintain it when it expands. From there everyone should be able to check for updates and its project scoped 馃槃 I also have the same CI command that everyone can trigger on the main branches, works like a charm!
@officert I'm glad you got that one working! Now we had some trouble in with the environment when publishing it to Expo. After intensive testing en prototyping we decided to go for babel-plugin-inline-dotenv. This one has some really good advantages, some of them:
REACT_NATIVE_Hope this helps anyone! Cheers
I've tried adding transform-inline-environment-variables to my babelrc file and i've tried REACT_NATIVE_***=*** npm start -- --reset-cache. Nothing works. All i have in my process.env is {"NODE_ENV": "production"} even in development mode... (using react-native-scripts)
@kiorq any update, i have same issue nothing works
Nope, not any luck what so ever. I have to manually change a const in a config.js file that switches between config.dev.js or config.prod.js depending on the value of the const. :/
@kiorq @Sunil6591 with transform-inline-environment-variables, process.env is left untouched, you have to use process.env.YOUR_VARIABLE
In a web react app it's possible to set env variables through .env, thanks to create-react-app, wich contains react-scripts.
With create-react-app:
"start": "react-scripts start"
With ejected create-react-native-app:
"start": "node node_modules/react-native/local-cli/cli.js start",
It's possible to setup something like this in a ejected create-react-native-app?
any updates?
https://github.com/luggit/react-native-config I have done something like which is mentioned in this link. But when I change the .env file on the fly and just reload the application it won鈥檛 work because it bundles with the earlier env variables. Can you suggest a way to change that?
For folks still reading this, if you just need a simple "is dev or prod" check, looks like you can use the __DEV__ flag, which is set to true in dev, and false on prod.
Its works with restarting ios simulator at my environment.
My script is like below.
"ios": "REACT_NATIVE_SOME_VAL=1 react-native-scripts ios",
Run it with yarn:
$ yarn ios
Most helpful comment
@dikaiosune so I'm an idiot. I completely forgot that the CRA process ignores all env variables that didn't start with
REACT_and looks like you guys applied the same thing, except you expect aREACT_NATIVE_to start after I rtfm in the Environment Variables section 馃ぃSo, it works, huzzah!
TL;DR: For anybody following my thread, you can do this via the
startscript like so:And it works! Be sure to set environment variables to start with
REACT_NATIVE_or it will be ignored, similar to how environment variables that don't start withREACT_are ignored by CRA.Note: You don't actually need to add the
babel-plugin-transform-inline-environment-variablesplugin above, it seems to work fine without it.Update: Got a PR out to address the documentation gap. Hope it helps someone! https://github.com/react-community/create-react-native-app/pull/125