- Published on
Automatically Switch Node Versions with nvm for React Native Projects
- Authors

- Name
- Mick MacCallum
- @0x7fs
If you work on multiple React Native or Expo projects, you've probably hit build errors caused by using the wrong Node version. Maybe the Metro bundler crashes, or pod install fails with some obscure Ruby error, or your CI passes but your local build doesn't. Often the culprit is a Node version mismatch.
The fix is to lock your project to a specific Node version and have your shell switch to it automatically.
The Problem
React Native and Expo projects can be picky about Node versions. Common symptoms of version mismatches:
ENOENTorEACCESerrors duringnpm install- Metro bundler crashes on startup
- Native build failures that work fine in CI
- "Unsupported engine" warnings you've been ignoring
- Mysterious differences between team members' machines
The root cause is usually that your global Node version doesn't match what the project expects.
Installing nvm
If you're not already using nvm, it's a tool that lets you install and switch between multiple Node versions on the same machine. Install it with:
curl -o- https://raw.githubusercontent.com/nvm-sh/nvm/v0.40.1/install.sh | bash
Then restart your terminal. You can verify it's working with nvm --version. See the nvm GitHub repo for more details.
Step 1: Add an .nvmrc File
Create a .nvmrc file in your project root with the Node version you want:
echo "20" > .nvmrc
Or be more specific:
echo "20.11.0" > .nvmrc
This file tells nvm which version to use, but by default you still have to run nvm use manually every time you open the project.
Step 2: Auto-Switch on Directory Change
Add this to your ~/.zshrc after your nvm initialization:
# Auto-switch Node version based on .nvmrc
autoload -U add-zsh-hook
load-nvmrc() {
local nvmrc_path
nvmrc_path="$(nvm_find_nvmrc)"
if [ -n "$nvmrc_path" ]; then
local nvmrc_node_version
nvmrc_node_version=$(nvm version "$(cat "${nvmrc_path}")")
if [ "$nvmrc_node_version" = "N/A" ]; then
nvm install
elif [ "$nvmrc_node_version" != "$(nvm version)" ]; then
nvm use
fi
elif [ -n "$(PWD=$OLDPWD nvm_find_nvmrc)" ] && [ "$(nvm version)" != "$(nvm version default)" ]; then
echo "Reverting to nvm default version"
nvm use default
fi
}
add-zsh-hook chpwd load-nvmrc
load-nvmrc
Now when you cd into a directory with an .nvmrc, nvm automatically switches to that version. If the version isn't installed, it installs it for you. When you leave the directory, it reverts to your default.
Reload your shell config:
source ~/.zshrc
Step 3: Enforce the Version in package.json
The .nvmrc handles local development, but you should also document the requirement in package.json so npm and yarn can warn users:
{
"engines": {
"node": ">=20.0.0"
}
}
This won't block installs by default, but it will show a warning. To make npm strict about it, users can set:
npm config set engine-strict true
Step 4: Lock the Package Manager Too
Different versions of npm can produce different package-lock.json files, leading to "works on my machine" issues. The packageManager field in package.json locks this down:
{
"packageManager": "npm@10.2.4"
}
With Corepack enabled (it ships with Node but is off by default), this ensures everyone uses the exact same npm version:
corepack enable
Now if someone tries to run npm install with the wrong version, they'll get an error instead of a subtly different lockfile.
Putting It Together
A complete setup looks like this:
.nvmrc:
20.11.0
package.json:
{
"name": "my-app",
"engines": {
"node": ">=20.0.0"
},
"packageManager": "npm@10.2.4"
}
Add both files to version control. New team members clone the repo, cd into it, and nvm handles the rest. No more "what Node version are you on?" in Slack.
Expo and React Native Specific Notes
Expo's managed workflow is generally more forgiving about Node versions, but the bare workflow and standalone React Native projects often aren't. Check the React Native environment setup docs for the currently recommended Node version.
If you're using Expo, their requirements page lists supported Node versions. When in doubt, use the latest LTS.
Continue Learning
How to Change the Default Screenshot Folder on macOS
Stop cluttering your Desktop with screenshots. Here's how to save them somewhere else using Terminal or the Screenshot app.
Prevent macOS from Creating .DS_Store Files on Network and USB Drives
Stop macOS from littering .DS_Store files on network shares and USB drives with a simple Terminal command. Keep your external storage clean and your repositories tidy.