
Hi there!
If you've been working with React Native, you've likely encountered emulator issues. You run the React Native command, but the emulator isn’t detected. Even after setting all the necessary environment variables in your .zshrc, .bash_profile, or similar files, it still doesn’t work.
Here are some common problems and fixes:
Emulator Not Found: This can happen if the Android SDK path isn't correctly set. Double-check that the ANDROID_HOME and PATH environment variables point to the correct directories. You can add these lines to your .zshrc or .bash_profile:
export ANDROID_HOME=$HOME/Library/Android/sdk export PATH=$PATH:$ANDROID_HOME/emulator export PATH=$PATH:$ANDROID_HOME/tools export PATH=$PATH:$ANDROID_HOME/tools/bin export PATH=$PATH:$ANDROID_HOME/platform-tools
After making these changes, restart your terminal or run source ~/.zshrc (or source ~/.bash_profile).
Watchman Errors: Sometimes, Watchman—Facebook’s file watching service—can cause issues with stale file caches. To fix this, run:
watchman watch-del-all
Then, restart your React Native server.
adb reverse to Connect to localhost: If your app cannot connect to localhost from within the Android emulator, you might need to run:
adb reverse tcp:8081 tcp:8081
This command routes traffic from the emulator to your local machine. Make sure adb is accessible from your terminal.
Clear Cache and Rebuild: If you still face issues, try clearing the cache and rebuilding the project:
npm start -- --reset-cache cd android && ./gradlew clean cd ios && xcodebuild clean
Then run your React Native app again.
Using react-native run-android or run-ios Directly: If the emulator is not starting correctly from your IDE or terminal, try running the app directly with:
npx react-native run-android npx react-native run-ios
Debugging these issues can be frustrating, but these steps have helped me solve many common problems.
I created an easy-to-use script too
const {spawn, exec} = require('child_process');
const path = require('path');
// Define paths
const projectPath = path.resolve();
// Define commands
const watchDelCommand = `watchman watch-del '${projectPath}'`;
const watchProjectCommand = `watchman watch-project '${projectPath}'`;
// Function to execute commands
const clearWatchman = () => {
// Execute watch-del command
exec(watchDelCommand, (error, stdout, stderr) => {
if (error) {
console.error(`Error executing watch-del command: ${error.message}`);
return;
}
if (stderr) {
console.error(`stderr: ${stderr}`);
return;
}
console.log(`watch-del command executed successfully: ${stdout}`);
// Execute watch-project command
exec(watchProjectCommand, (error, stdout, stderr) => {
if (error) {
console.error(
`Error executing watch-project command: ${error.message}`,
);
return;
}
if (stderr) {
console.error(`stderr: ${stderr}`);
return;
}
console.log(`watch-project command executed successfully: ${stdout}`);
});
});
};
async function reverseAdb() {
console.log('Running... adb reverse tcp:8080 tcp:8080');
// After the emulator has started adb reverse tcp:8080 tcp:8080
const adbReverse = spawn('adb', ['reverse', 'tcp:8080', 'tcp:8080']);
await new Promise((resolve, reject) => {
let output = '';
adbReverse.stdout.on('data', data => {
output += data.toString();
});
adbReverse.on('close', () => {
resolve();
});
adbReverse.stderr.on('error', reject);
}).catch(error => console.error('Error reversing ADB port to 8080:', error));
}
async function runEmulator() {
try {
clearWatchman();
// Check for running emulator
const adbDevices = spawn('adb', ['devices']);
const devices = await new Promise((resolve, reject) => {
let output = '';
adbDevices.stdout.on('data', data => {
output += data.toString();
});
adbDevices.on('close', () => {
resolve(output.includes('emulator'));
});
adbDevices.stderr.on('error', reject);
});
if (devices) {
console.log('Emulator is already running');
reverseAdb();
return;
}
// Get list of available emulators
const emulatorList = spawn('emulator', ['-list-avds']);
const emulatorName = await new Promise((resolve, reject) => {
let output = '';
emulatorList.stdout.on('data', data => {
output += data.toString();
});
emulatorList.on('close', () => {
const lines = output.split('\n').filter(Boolean); // Filter out empty lines
if (lines.length === 0) {
reject(new Error('No AVDs found'));
} else {
resolve(lines[lines.length - 1]); // Get the last non-empty line
}
});
emulatorList.stderr.on('error', reject);
});
// Start the emulator in detached mode
const emulatorProcess = spawn('emulator', ['-avd', emulatorName], {
detached: true,
stdio: 'ignore',
});
emulatorProcess.unref(); // Allow the parent process to exit independently of the child
reverseAdb();
console.log(`Starting emulator: ${emulatorName}`);
} catch (error) {
console.error('Error running emulator:', error);
}
}
runEmulator();
// package.json
"scripts": {
...
"dev:android": "yarn android:emulator && npx react-native@latest start",
"android:emulator": "node runEmulator.js",
...
},
By using the script above, you can run both the emulator and React Native simultaneously.
Thanks for reading!
The above is the detailed content of A Script To Help React Native Developers. For more information, please follow other related articles on the PHP Chinese website!