[go: up one dir, main page]

0% found this document useful (0 votes)
35 views78 pages

Interview Question

React Native primarily uses JavaScript engines to execute code, with Hermes being the current default engine since version 0.70 due to its mobile optimizations, faster startup times, and lower memory usage. Historically, React Native has utilized JavaScriptCore, V8, and Chakra, each with unique features and limitations. The document also discusses the evolution of these engines and their impact on performance and developer experience in mobile applications.

Uploaded by

shreyas
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
0% found this document useful (0 votes)
35 views78 pages

Interview Question

React Native primarily uses JavaScript engines to execute code, with Hermes being the current default engine since version 0.70 due to its mobile optimizations, faster startup times, and lower memory usage. Historically, React Native has utilized JavaScriptCore, V8, and Chakra, each with unique features and limitations. The document also discusses the evolution of these engines and their impact on performance and developer experience in mobile applications.

Uploaded by

shreyas
Copyright
© © All Rights Reserved
We take content rights seriously. If you suspect this is your content, claim it here.
Available Formats
Download as PDF, TXT or read online on Scribd
You are on page 1/ 78

Version

React Native primarily uses JavaScript engines to interpret and execute


JavaScript code. Here's a detailed look at the engines React Native has used
historically and currently:

🔍 Current JavaScript Engine in React Native


1. Hermes (Default Engine for React Native)

Introduced in: React Native 0.60+ (2019)

Key Features:

Optimized for mobile apps.

Faster app startup time.

Lower memory usage.

Precompilation of JavaScript bytecode to improve runtime


performance.

Why Hermes?:

It provides performance improvements, especially on low-end


devices.

React Native team made Hermes the default starting from React
Native 0.70.

📜 List of Past Engines Used in React Native


1. JavaScriptCore (JSC)

Used in: Early versions of React Native (before 0.60 and optionally in
later versions).

Key Features:

Apple's default engine for Safari and iOS.

Cross-platform support (used in both Android and iOS).

Lightweight but lacked optimizations for mobile.

Limitations:

Version 1
Not as fast as Hermes for mobile-specific use cases.

Higher memory consumption compared to Hermes.

2. V8

Optional: Community-maintained support.

Key Features:

Google's JavaScript engine used in Chrome and Node.js.

High performance for apps requiring advanced JavaScript features.

Usage:

Available as a custom option for advanced users.

Libraries like react-native-v8 allow developers to integrate V8.

3. Chakra (Windows Support)

Used in: React Native for Windows.

Key Features:

Microsoft’s JavaScript engine used in Edge (pre-Chromium).

Optimized for the Windows ecosystem.

Limitations:

Limited usage in the React Native ecosystem outside of Windows


development.

Key Comparisons

Optimized for
Engine Platform Performance Memory Usage
Mobile

Hermes iOS, Android 🔥 High 🔋 Low ✅ Yes


JSC iOS, Android ⚡ Moderate ⚡ Moderate ❌ No
V8 Android 🚀 Very High 🔋 Low ❌ No
Chakra Windows ⚡ Moderate ⚡ Moderate ❌ No
How to Check/Use the Engine in React Native
1. Hermes Check:

Version 2
Verify in your android/app/build.gradle or ios/Podfile :

enableHermes: true // Enables Hermes

2. Switching Engines:

Disable Hermes and revert to JSC:

enableHermes: false

Conclusion
Hermes is now the default and preferred engine in React Native due to its
mobile-centric optimizations.

Advanced users can still opt for V8 or JSC based on specific needs.

Would you like guidance on enabling/disabling these engines in your project?


😊
Here’s a detailed backstory for each JavaScript engine used in React Native,
focusing on why shifts happened, the problems they addressed, and the
functionality upgrades they brought:

1. JavaScriptCore (JSC)

Backstory: Why It Was Used


JSC was the default JavaScript engine in React Native from its inception
(2015) because it was:

Lightweight and cross-platform.

Already available as the default JavaScript engine in iOS (Safari).

Problems with JSC


Memory Usage:

It wasn’t optimized for mobile apps, leading to higher memory


consumption.

Performance on Android:

Version 3
Android used a custom version of JSC (not updated frequently), leading
to performance and compatibility issues.

Startup Time:

Parsing and executing JavaScript caused longer startup times in mobile


apps.

Modern JavaScript Features:

Limited support for newer ES6+ features (until an updated version was
introduced in 2018).

Key Improvements Over Time


In 2018, the React Native team upgraded JSC for Android to support ES6+
features like async/await .

Despite this, JSC was not designed with mobile-specific optimizations in


mind, prompting the need for alternatives.

2. Hermes (2019 - Current Default)

Backstory: Why the Shift to Hermes


React Native introduced Hermes in version 0.60 (2019) as an open-source
JavaScript engine optimized for mobile apps, specifically for Android
initially.

Key Goals:

Improve startup time.

Reduce memory usage.

Provide better performance for low-end devices.

Problems Hermes Solved


1. Startup Time:

Hermes introduced precompiled JavaScript bytecode (ahead-of-time


compilation), reducing the time spent parsing JS during runtime.

Apps started faster compared to JSC, especially on Android.

2. Memory Usage:

Version 4
Hermes had lower memory consumption due to its compact bytecode
and garbage collection optimizations.

3. Performance on Low-End Devices:

Designed with low-memory devices in mind, Hermes improved


performance on older Android phones significantly.

4. Consistency Across Platforms:

Provided a consistent runtime environment for Android and iOS


(introduced later).

Functionality and Upgrades


Ahead-of-Time (AOT) Compilation:

JavaScript is compiled to bytecode during the build process, reducing


runtime workload.

Smaller APK/IPA Size:

Optimized for lightweight apps with reduced binary size.

Newer JavaScript Features:

Supported modern ES6+ features efficiently.

Debugging Tools:

Introduced integration with Chrome DevTools for debugging Hermes


apps.

3. V8 (Optional, Community-Supported)

Backstory: Why Consider V8


V8 is Google’s JavaScript engine, powering Chrome and Node.js. While not
officially integrated into React Native, react-native-v8 was introduced by
the community to leverage its performance.

Developers opt for V8 in scenarios where:

Extremely high JavaScript performance is required.

Features like WebAssembly are needed.

Problems V8 Solved

Version 5
High-Performance Apps:

Offers better raw JavaScript performance compared to Hermes or JSC.

Compatibility with Node.js:

Developers coming from Node.js environments find V8 more familiar.

Functionality and Upgrades


Just-in-Time (JIT) Compilation:

V8 compiles JavaScript to native machine code at runtime for maximum


performance.

Advanced Debugging:

Features robust debugging tools and performance profilers.

WebAssembly Support:

Enables apps to run WebAssembly modules for intensive computational


tasks.

4. Chakra (Used in React Native Windows)

Backstory: Why Chakra


Microsoft developed Chakra as the JavaScript engine for Edge (pre-
Chromium).

It was used in React Native for Windows to integrate with the Windows
ecosystem efficiently.

Problems Chakra Solved


Windows-Specific Optimizations:

Provided seamless integration with Windows APIs.

Performance on Windows:

Tailored for Windows-based React Native apps, ensuring smooth


execution.

Functionality and Upgrades


Focused on improving the Windows development experience.

Version 6
Supported modern JavaScript features for compatibility with React Native.

Why Shift Between Engines?

Core Problems That Drove Change


1. Performance:

Startup times, memory usage, and execution speed needed


optimization for mobile.

2. Modern JavaScript Features:

Engines like JSC lagged behind in supporting newer JS syntax.

3. Low-End Device Compatibility:

Hermes emerged as a solution to serve apps on low-resource devices


effectively.

React Native’s Engine Evolution


JSC: Great for cross-platform but not optimized for mobile apps.

Hermes: Solved startup, memory, and low-end device challenges.

V8: Offers unmatched performance but is not mobile-focused.

Chakra: Optimized for Windows-specific React Native apps.

Would you like guidance on how to enable specific engines or compare their
real-world performance? 😊
Why is Hermes the Current Default JavaScript Engine in React
Native?
The shift to Hermes as the default engine was a result of React Native's focus
on mobile-specific optimizations and the need to address key limitations of
previous engines like JavaScriptCore (JSC). Here's a detailed breakdown of
why Hermes is the current default and how it improves performance:

Limitations of Previous Engines


1. JavaScriptCore (JSC):

Version 7
High Memory Usage: JSC was not designed for resource-constrained
mobile devices, leading to inefficient memory use.

Slower Startup Time: Parsing and executing JavaScript at runtime in


JSC added overhead.

Android vs. iOS Inconsistency: Different versions of JSC on Android


and iOS caused unpredictable behavior in cross-platform apps.

Limited Support for Modern JS Features: While JSC supported modern


ES6+ syntax after updates, it still lagged in performance compared to
newer engines.

2. V8:

While extremely performant, V8 is not optimized for mobile use. Its


large binary size and focus on desktop/browser environments made it
less ideal for React Native.

Hermes: Improvements Over Previous Versions

1. Performance Enhancements
Startup Time Reduction:

Hermes uses Ahead-of-Time (AOT) Compilation to precompile


JavaScript to bytecode during the build process. This eliminates the
need to parse and compile JavaScript during app startup, significantly
reducing startup times.

Memory Optimization:

Hermes reduces memory usage through compact bytecode and


efficient garbage collection, making it ideal for low-end devices.

By freeing memory resources, it allows the app to run more smoothly.

2. Consistency Across Platforms


Hermes provides a consistent runtime for Android and iOS. Developers no
longer need to worry about discrepancies between JavaScriptCore
versions.

3. Optimized for Mobile Apps


Hermes was designed specifically with mobile in mind:

Version 8
It prioritizes resource efficiency.

Provides features like inline caching to improve runtime performance.

4. Smaller App Size


The Hermes bytecode engine adds minimal overhead to the APK/IPA size
compared to alternatives like V8.

5. Modern JavaScript Support


Hermes keeps pace with modern JavaScript features, ensuring
compatibility with the latest language standards.

6. Improved Debugging Tools


Hermes integrates with Chrome DevTools, allowing developers to debug
apps efficiently. It also supports React Native Flipper for inspecting
memory and performance.

Performance Benchmarks

Comparing Hermes vs. JSC:


Metric Hermes JSC

Startup Time
🔥 Faster (30-50% ❌ Slower due to runtime
improvement) parsing

Memory Usage 🔋 Lower (compact bytecode) ⚡ Higher


App Size (Increase) ⚖️ Minimal ⚖️ Minimal
Runtime
Performance
🚀 Optimized ⚡ Decent
Consistency ✅ Same for iOS/Android ❌ Discrepancies
Why Hermes Was Made Default in React Native 0.70
Hermes became the default engine starting with React Native 0.70
because:

It aligns with React Native's mobile-first philosophy.

Provides out-of-the-box optimizations for performance and memory.

Version 9
Eliminates the need for developers to configure the engine manually,
simplifying app development.

Key Features Introduced in Recent Hermes Versions


1. Garbage Collection Improvements:

Improved garbage collection reduces memory fragmentation and


boosts app performance.

2. Fast Bytecode Loading:

Optimized for loading precompiled bytecode faster than ever.

3. Enhanced Debugging:

Better integration with developer tools like Flipper and Chrome


DevTools.

4. Support for Latest JS Features:

Continuous updates ensure compatibility with modern ES6+ features.

In Summary
Hermes improves on the shortcomings of JSC by focusing on:

Faster startup times.

Lower memory usage.

Mobile-specific optimizations.

Consistency and developer productivity.

It was chosen as the default engine because it aligns with React Native's
mission to deliver the best mobile experience on all devices, including low-
end ones.

Would you like to see how to enable or benchmark Hermes in your own React
Native project?😊
🚀 React Native's Significant Improvements
🆕 New Architecture in React Native 0.76
Version 10
📅 Released: October 2024
✨ Key Enhancements:
⚡ Full Support for Modern React Features:
Adds features like:

🌀 Suspense for data fetching.


🎭 Transitions for smoother UI updates.
🔄 Automatic Batching for better state management.
🛠️ useLayoutEffect for layout-dependent effects.
Improvement: Builds highly responsive and efficient apps!

🛡️ New Native Module & Component Systems:


Introduces type-safe interfaces for accessing native modules directly.

Impact: Reduces reliance on the JavaScript bridge for better


performance.

🏗️ Gradual Migration Path:


Simplifies transitioning existing projects to the New Architecture
without requiring major rewrites.

💎 Hermes JavaScript Engine


Hermes remains the default engine, with continuous optimizations making it
faster and more efficient.
✨ Recent Upgrades:
⚡ Faster Startup Times:
Enhanced bytecode generation reduces app launch times.

🔋 Reduced Memory Usage:


Improved memory management lowers RAM consumption, especially
helpful on low-end devices.

📦 Smaller App Sizes:


Refinements shrink the engine’s footprint, minimizing APK/IPA size.

🌟 Future Developments in React Native


Version 11
🔧 Upcoming Improvements:
🛠️ Enhanced Developer Tools:
Unified DevTools for a more seamless and productive development
experience.

🏎️ Improved Build Processes:


Faster builds and simpler configurations are on the way!

✨ Why It Matters?
React Native's focus on performance, developer experience, and modern
features ensures it remains a powerful framework for building cross-platform
mobile applications! 💻📱

JavaScript Engine in React.js (Today)


React.js, unlike React Native, does not have a specific JavaScript engine of its
own. Instead, React.js relies on the JavaScript engine of the browser it is
running on. These engines are responsible for interpreting and executing
JavaScript code in web applications.

Here are the engines commonly used in modern browsers that power React.js
applications:

1. V8 (Google Chrome, Chromium-based Browsers)


Used In: Google Chrome, Edge (Chromium), Opera.

Key Features:

Just-In-Time (JIT) compilation for converting JavaScript to machine


code.

Optimizations for modern JavaScript features (e.g., ES6+).

High-performance garbage collection for managing memory efficiently.

Version 12
Why It's Important for React:

Provides excellent execution speed for React's reconciliation and


rendering processes.

Great support for advanced ES6+ syntax used in React applications.

2. SpiderMonkey (Mozilla Firefox)


Used In: Mozilla Firefox.

Key Features:

First JavaScript engine ever developed.

Implements modern ECMAScript standards, including ES6+.

Features Just-In-Time (JIT) compilation and garbage collection.

Why It's Important for React:

Optimized for React's usage patterns, like functional components and


JSX compilation.

Provides competitive performance with modern JavaScript frameworks.

3. JavaScriptCore (JSC - Safari)


Used In: Apple Safari (macOS, iOS).

Key Features:

Lightweight and fast JavaScript engine.

Introduced ahead-of-time (AOT) compilation to improve performance.

Why It's Important for React:

Ensures smooth execution of React apps on Apple devices.

Reliable for rendering React apps in Safari browsers.

4. Chakra (Legacy Edge)


Used In: Microsoft Edge (prior to the Chromium switch in 2020).

Current Status: No longer actively used in mainstream browsers.

Key Features:

Version 13
Optimized for Windows systems.

Supported ES6+ features and JIT compilation.

Why It's Important for React:

Was important for React apps targeting older versions of Edge but is
now obsolete.

Modern Trends in React.js Performance


1. React 18 and Concurrent Rendering:

The concurrent rendering feature introduced in React 18 heavily relies


on the JavaScript engine's ability to handle asynchronous tasks
efficiently.

V8, SpiderMonkey, and JSC are all optimized to support React’s modern
asynchronous features.

2. WebAssembly Integration:

Some React.js libraries leverage WebAssembly (e.g., for high-


performance computations), which all modern engines support.

Conclusion
The choice of the JavaScript engine for React.js depends on the browser:

Chrome/Chromium-based: V8 (Fast and modern).

Firefox: SpiderMonkey (Highly optimized for ES6+).

Safari: JavaScriptCore (Lightweight and efficient).

React itself is designed to work seamlessly across all modern engines,


ensuring consistent performance regardless of the browser. Would you like
guidance on optimizing React for specific engines or browsers? 😊
}

Certainly! Here's a list of libraries and modules that can be used in JavaScript
as well as React Native, along with brief explanations for each:

Version 14
🔧 Libraries/Modules Usable in Both JavaScript & React Native
1. Lodash
Purpose: Utility library for working with arrays, objects, strings, etc.

Use Cases: Data manipulation, deep cloning, debounce functions.

Example:

import _ from 'lodash';

const array = [1, 2, 3, 4, 5];


const chunked = _.chunk(array, 2); // [[1, 2], [3, 4],
[5]]
console.log(chunked);

2. Moment.js / Day.js
Purpose: Date and time manipulation.

Use Cases: Formatting dates, time zone handling.

Example:

import moment from 'moment';

const now = moment().format('YYYY-MM-DD');


console.log(now); // Output: Current date in specified f
ormat

3. Axios
Purpose: HTTP client for making API requests.

Use Cases: Fetching data, handling RESTful APIs.

Example:

import axios from 'axios';

axios.get('https://jsonplaceholder.typicode.com/posts')

Version 15
.then(response => console.log(response.data))
.catch(error => console.error(error));

4. Redux / Redux Toolkit


Purpose: State management.

Use Cases: Centralized application state management.

Example:

import { configureStore, createSlice } from '@reduxjs/to


olkit';

const counterSlice = createSlice({


name: 'counter',
initialState: 0,
reducers: {
increment: state => state + 1,
decrement: state => state - 1,
},
});

const store = configureStore({


reducer: counterSlice.reducer,
});

store.dispatch(counterSlice.actions.increment());
console.log(store.getState()); // 1

5. React Query
Purpose: Server state management and data fetching.

Use Cases: Fetch, cache, and update data.

Example:

import { useQuery } from '@tanstack/react-query';

function App() {

Version 16
const { data, error, isLoading } = useQuery(['posts'],
() =>
fetch('https://jsonplaceholder.typicode.com/posts').
then(res => res.json())
);

if (isLoading) return <Text>Loading...</Text>;


if (error) return <Text>Error!</Text>;

return (
<FlatList
data={data}
renderItem={({ item }) => <Text>{item.title}</Text
>}
/>
);
}

6. Styled Components
Purpose: CSS-in-JS for styling.

Use Cases: Dynamic styling for components.

Example:

import styled from 'styled-components/native';

const StyledButton = styled.Button`


background-color: blue;
color: white;
`;

function App() {
return <StyledButton title="Press Me" />;
}

7. Formik
Purpose: Form management.

Version 17
Use Cases: Handling form validation and state.

Example:

import { Formik } from 'formik';

function App() {
return (
<Formik
initialValues={{ name: '' }}
onSubmit={values => console.log(values)}
>
{({ handleChange, handleSubmit, values }) => (
<TextInput
onChangeText={handleChange('name')}
value={values.name}
onSubmitEditing={handleSubmit}
/>
)}
</Formik>
);
}

8. Yup
Purpose: Schema validation.

Use Cases: Validating forms or objects.

Example:

import * as Yup from 'yup';

const schema = Yup.object({


name: Yup.string().required('Name is required'),
age: Yup.number().min(18).required('Age is required'),
});

schema.validate({ name: '', age: 17 })

Version 18
.catch(err => console.error(err.errors)); // ["Name is
required", "Age must be greater than or equal to 18"]

9. React Navigation (React Native Specific but Inspired by JS


Libraries)
Purpose: Navigation for React Native.

Use Cases: Managing routes, stack navigators.

Example:

import { NavigationContainer } from '@react-navigation/n


ative';
import { createStackNavigator } from '@react-navigation/
stack';

const Stack = createStackNavigator();

function App() {
return (
<NavigationContainer>
<Stack.Navigator>
<Stack.Screen name="Home" component={HomeScreen}
/>
</Stack.Navigator>
</NavigationContainer>
);
}

10. Victory / Recharts


Purpose: Data visualization.

Use Cases: Creating charts like bar, pie, line, etc.

Example:

import { VictoryBar } from 'victory-native';

function App() {

Version 19
return (
<VictoryBar
data={[
{ x: 1, y: 2 },
{ x: 2, y: 3 },
{ x: 3, y: 5 },
]}
/>
);
}

💡 Additional Libraries Worth Mentioning


Jest: Testing framework for unit tests.

React Hook Form: Lightweight form library.

AsyncStorage: Persistent storage for React Native.

Socket.IO: Real-time communication via WebSockets.

i18next: Internationalization and localization.

Would you like to dive deeper into the implementation of any of these libraries?

👔 Answer to the Interviewer


Question: What determines if a library or component can be used in both
JavaScript and React Native? Can components using window or document be
used in React Native or only JavaScript?

Answer:

1. Pure JavaScript Libraries/Components:

Any library or component written entirely in JavaScript with no


platform-specific dependencies (like DOM or native APIs) can be used
in both JavaScript environments (like browsers) and React Native.

Examples:

Lodash : A utility library for data manipulation.

Version 20
Axios : A popular library for making HTTP requests.

Redux : A state management library.

2. Native-Specific Libraries/Components:

Libraries that rely on platform-native code (e.g., iOS or Android APIs)


can only be used in React Native. They cannot run in a JavaScript
environment like a browser because they depend on mobile-specific
functionalities.

Examples:

react-native-camera : Uses the device's camera.

react-native-geolocation-service : Accesses GPS functionality.

3. DOM-Specific Libraries:

Components or libraries that use window , document , or any DOM API are
JavaScript-specific because the DOM exists only in the browser.

React Native does not use a DOM. Instead, it uses a virtualized UI layer
that maps React Native components (like View , Text , etc.) to native
mobile components.

Examples:

A component relying on document.getElementById() is JavaScript-only.

A React Native Text component, on the other hand, is native-


specific.

4. Polyfills/Bridging Libraries:

Some libraries bridge the gap between the browser and React Native by
implementing polyfills or fallback mechanisms.

Example:

allows React Native components to run in a browser


react-native-web

by mapping them to equivalent DOM elements.

5. Key Takeaway:

Cross-platform usability depends on whether the library is written in


pure JavaScript or relies on platform-specific code. Libraries written for
the DOM or native mobile features are inherently limited to their
respective platforms.

Version 21
❌ Mistakes to Avoid While Answering:
1. Oversimplification:

The original answer lacked examples and nuance. Simply stating, "If
it's pure JavaScript, it works for both; otherwise, it's platform-specific,"
is incomplete.

An interviewer expects specific examples to demonstrate practical


knowledge.

2. Ignoring Edge Cases:

The original answer failed to mention libraries like react-native-web that


bridge the gap between environments. This shows an incomplete
understanding of cross-platform development.

3. Misuse of Terms:

Saying "window and document are React Native-specific" would be


incorrect because they are JavaScript-specific and do not exist in
React Native.

4. Not Explaining Why:

The original answer lacked a clear explanation of why certain libraries


work in some environments and not in others. Without understanding
this, the response feels shallow.

✔️ Correct Approach to Avoid These Mistakes:


1. Be Specific:

Use concrete examples for both pure JavaScript and native-specific


libraries. Examples make your answer relatable and demonstrate
experience.

2. Acknowledge Edge Cases:

Show that you’re aware of bridging solutions like react-native-web or


polyfills, which add depth to your answer.

3. Use Clear Terminology:

Clearly differentiate between JavaScript (browser) and React Native.


Emphasize the absence of DOM in React Native and the use of native
components instead.

Version 22
4. Structure Your Answer:

Break your answer into clear categories:

Pure JavaScript (works on both).

Native-specific (React Native only).

DOM-specific (JavaScript only).

Bridging libraries (special cases).

Example of Mistake by the Original Answer:


The original response lacked depth and examples. Simply stating
"components using window or document are JavaScript-specific" is correct
but doesn’t explain why.

The speaker didn’t acknowledge edge cases like libraries bridging


JavaScript and React Native.

The response was not structured, which can make it hard for an
interviewer to follow or assess knowledge.

🎯 Final Thoughts for the Interviewer’s Perspective:


A good answer must show clarity, examples, and consideration for edge
cases.

It’s not just about being correct but also showing depth of understanding.

Structure your response so it’s easy to follow and demonstrates confidence


in cross-platform development.

Would you like me to create a more concise version of this for quick notes?

Hermes is a JavaScript engine designed to improve performance for React


Native apps. Here’s how it is used across platforms:

Does Hermes Work on Android or iOS?


1. Initially:

Hermes was originally introduced for Android only in 2019 because


Android devices typically had slower JavaScript performance compared

Version 23
to iOS (which uses the highly optimized JavaScriptCore engine).

2. Current State (as of 2023):

Hermes is now supported on both Android and iOS. This allows


developers to use the same JavaScript engine for both platforms,
leading to:

Improved performance (faster startup times, reduced memory


usage).

Consistent behavior across platforms.

How Hermes Works in React Native:


React Native uses JavaScriptCore by default to execute JavaScript.

If you enable Hermes in your project:

Hermes replaces the default JavaScript engine on both platforms


(Android and iOS).

Key Notes:
Enabling Hermes is optional but highly recommended for most React Native
apps.

To enable Hermes, you must update your android/app/build.gradle and


ios/Podfile .

Misconceptions:
Hermes is not specific to Android or iOS; it works on both.

The default engine for iOS is JavaScriptCore, but Hermes can replace it for
optimized performance.

Would you like me to explain how to enable Hermes in a React Native project?

In an interview, it’s essential to be honest and transparent, but also to provide a


proactive and thoughtful response. Here's how you can frame your answer
while demonstrating awareness of the topic:

Answer Example:

Version 24
"I haven’t had the opportunity to work directly on iOS React Native
development because I currently develop on a Windows environment and don’t
have access to an iOS device for testing. However, I’m familiar with the process
of enabling Hermes on both Android and iOS in React Native. From what I
know, Hermes is supported on both platforms and is typically enabled through
the project configuration. I would be happy to work with the team to ensure
that Hermes is properly set up on iOS if needed."

Why This Works:


1. Honesty: You acknowledge that you haven’t worked directly with iOS due
to the limitations of your current setup, which is perfectly fine.

2. Proactive Knowledge: You show awareness of Hermes and its role in both
Android and iOS development, even though you haven’t personally worked
on iOS.

3. Positive Outlook: You express a willingness to learn or work with the team
to ensure Hermes is set up on iOS. This demonstrates flexibility and a
growth mindset.

Mistake to Avoid:
Avoid sounding like a limitation. Instead of focusing only on the fact that
you don’t have an iOS device, focus on your proactive learning and how
you would overcome such challenges in the future.

This approach gives the impression that you are problem-solving and ready to
take on new tasks even if they are outside of your current experience.

How to Enable Hermes in iOS for React Native:


Yes, Hermes works for iOS as well, and it's relatively simple to enable it in your
React Native project. Here’s a quick guide on how to do it:

Steps to Enable Hermes in iOS:


1. Ensure You Have the Right Version of React Native:
Hermes is supported from React Native 0.65 onwards. If you're using an
older version, you'll need to upgrade your project.

2. Update Podfile :

Open the ios/Podfile of your React Native project.

Version 25
Add the following line to enable Hermes for iOS:

use_react_native!(:path => config[:reactNativePath],


:hermes_enabled => true)

3. Install Pods:

Run the following command to install the required dependencies:

cd ios
pod install

4. Clear Cache:

Clean the React Native build cache to ensure that everything is


configured properly:

npx react-native clean

5. Rebuild Your Project:

After enabling Hermes and updating the dependencies, rebuild your


project:

npx react-native run-ios

Is Hermes Supported in iOS?


Yes, Hermes works on iOS as well as Android.

It helps with faster startup times, reduced memory consumption, and


improved performance overall.

Advantages of Using Hermes on iOS:


Faster app startup.

Lower memory usage compared to the default JavaScriptCore engine used


by iOS.

More predictable performance.

Version 26
Common Issues:
Ensure your Xcode version is compatible with the version of React Native
you're using. Sometimes, issues can arise due to version mismatches.

Would you like a more detailed explanation of any step or encounter any
specific issue during setup?

Detailed breakdown of what happens when you modify the Podfile to enable
Hermes in iOS for React Native.

Before Enabling Hermes (Default Podfile Configuration):


By default, the Podfile doesn't specifically mention enabling Hermes. The
Podfile usually looks something like this before you enable Hermes:

platform :ios, '10.0'

target 'YourApp' do
config = use_native_modules!

# Add React Native dependencies here.

# Other iOS-related configuration...


end

At this point, the default JavaScript engine ( JavaScriptCore ) will be used for the
iOS build.

After Enabling Hermes (Modified Podfile ):


To enable Hermes for iOS, you need to explicitly update the Podfile like this:

1. Open the ios/Podfile of your React Native project.

2. Find the use_react_native! method inside the target block.

3. Update it to enable Hermes, by adding the :hermes_enabled => true flag.

Here’s how your Podfile should look after the change:

Version 27
platform :ios, '10.0'

target 'YourApp' do
config = use_native_modules!

# Enable Hermes by setting :hermes_enabled to true


use_react_native!(:path => config[:reactNativePath], :her
mes_enabled => true)

# Other iOS-related configuration...


end

What Was the Code Before?


Before adding the :hermes_enabled => true option, the use_react_native! line would
have been simpler, without the Hermes flag, and it would look something like
this:

use_react_native!(:path => config[:reactNativePath])

The default setting uses the JavaScriptCore engine (iOS's native JS engine),
and Hermes isn’t enabled in this case.

Explanation:
:path => config[:reactNativePath] : This specifies the location of the React
Native source code.

: This flag tells React Native to use the Hermes


:hermes_enabled => true

JavaScript engine instead of JavaScriptCore for better performance (faster


startup time, smaller bundle size, and improved memory usage).

After Making the Change:


Once you add :hermes_enabled => true , you need to run the following commands
to apply the changes:

1. Install Pods:

Version 28
cd ios
pod install

2. Clean Cache (optional but recommended):

npx react-native clean

3. Rebuild the Project:

npx react-native run-ios

Summary:
Before: The Podfile simply uses use_react_native! without enabling Hermes,
which defaults to JavaScriptCore.

After: You enable Hermes by adding :hermes_enabled => true to the


use_react_native! method, which makes Hermes the JavaScript engine for
iOS.

Would you like any further clarification or help with another part of the setup?

Container and Smart Components:


The distinction between Container Components and Smart Components is
often seen in React development. Here’s a quick breakdown of their roles,
features, and differences:

Smart Components (also called Stateful Components or


Container Components):
1. Purpose:

Smart Components are responsible for more than just rendering UI.
They handle state management and logic. They often connect to stores
(like Redux) or APIs to fetch data.

2. Features:

Version 29
State Management: Smart Components manage state locally and are
responsible for handling user interactions, form inputs, etc.

Business Logic: They can contain logic for how data is processed or
manipulated.

Props Handling: They pass data down to their child components


(typically Dumb Components or Presentational Components) via
props.

Side Effects: They often interact with external systems (e.g., network
requests, subscriptions, timers) and use hooks like useEffect to manage
side effects.

Example: A Smart Component can fetch data from an API, store it in its
local state, and pass it down to presentational components for
rendering.

3. Example:

import React, { useState, useEffect } from 'react';

const SmartComponent = () => {


const [data, setData] = useState(null);

useEffect(() => {
fetchData();
}, []);

const fetchData = async () => {


const response = await fetch('/api/data');
const result = await response.json();
setData(result);
};

return <DumbComponent data={data} />;


};

Container Components (also called Dumb Components or


Presentational Components):

Version 30
1. Purpose:

Container Components are often used to present UI and receive data


and actions as props. They are stateless and have minimal logic,
focusing only on how to render the UI.

2. Features:

Presentation: These components focus solely on UI rendering.

Receive Props: They are typically passed data from Smart Components
(or parent components) through props.

No State Management: These components usually don’t manage any


local state (other than simple UI state like visibility of modals or
toggles).

No Logic: They contain no business logic or side effects. They only


define the layout and the way data is displayed.

Reusability: Since they don’t have internal logic or dependencies, they


are easily reusable.

3. Example:

const DumbComponent = ({ data }) => {


return (
<div>
<h1>{data.title}</h1>
<p>{data.description}</p>
</div>
);
};

Key Differences:
Aspect Smart Component Dumb Component

Manages state, logic, and side


Purpose Renders UI based on props
effects

State
Handles its own state No internal state
Management

Business Logic Contains application logic No logic, only renders UI

Version 31
Props Passes data to Dumb Components Receives data via props

Reusability Less reusable (tied to logic) Highly reusable (pure UI)

Fetching data from API, managing Displaying data, formatting


Example
user input content

What Should Not Be Mistaken:


Smart Components are not "too complex": Just because they manage
state and logic doesn’t mean they should be excessively complex. They
should still be focused on one responsibility — managing the state and
passing data down to Dumb Components.

Dumb Components should not contain logic: The main job of a Dumb
Component is to render UI based on props. If it starts containing logic, it’s
no longer a "Dumb Component" in the pure sense, which can lead to
difficulties in maintaining the code.

In summary:

Smart Components = Handles state, logic, and connects to APIs or stores.

Dumb Components = Purely UI-focused, receiving props and rendering the


content.

Would you like further examples or deeper insights on how these components
interact?

InteractionManager in React Native:


You’re right in saying that React Native uses a single thread for the UI
rendering process by default. The UI thread is responsible for handling things
like rendering views, updating the layout, and processing animations. If we
overload the UI thread with heavy tasks (like fetching data from an API or
performing complex computations), it could cause jank (laggy or unresponsive
UI).

What is InteractionManager?
InteractionManager in React Native is designed to help manage and schedule
tasks in a way that minimizes blocking the UI thread. It allows you to schedule
tasks to be executed only after animations or interactions (like scrolls,
gestures, or transitions) have completed, keeping the UI smooth and
responsive.

Version 32
How does InteractionManager Work?
Scheduling tasks: You can use InteractionManager to defer tasks like API
calls or heavy computations so that they don’t block the UI thread during
animations or transitions.

Callbacks: InteractionManager allows you to define callbacks that are


executed when the UI is no longer busy with animations or user
interactions.

Why is it Important?
Performance: It helps in keeping the UI smooth and responsive by
offloading time-consuming tasks like API calls, calculations, or data
processing to be done after UI updates are complete.

Prevent Jank: By ensuring that the main thread (UI thread) is only dealing
with UI-related tasks, you prevent UI jank or lag during animations and
transitions.

Example: Using InteractionManager


Here’s how you can use InteractionManager to schedule an API call after an
animation has completed:

import React, { useEffect } from 'react';


import { View, Text, Animated, InteractionManager } from 'r
eact-native';

const MyComponent = () => {


const fadeAnim = new Animated.Value(0);

useEffect(() => {
// Start animation
Animated.timing(fadeAnim, {
toValue: 1,
duration: 2000,
useNativeDriver: true,
}).start();

// Use InteractionManager to defer the API call until a


nimation is complete

Version 33
InteractionManager.runAfterInteractions(() => {
// This will be executed after all animations and int
eractions finish
fetchDataFromAPI();
});
}, []);

const fetchDataFromAPI = async () => {


console.log('API Call Started');
const response = await fetch('https://api.example.com/d
ata');
const data = await response.json();
console.log('API Call Completed', data);
};

return (
<View>
<Animated.View
style={{
opacity: fadeAnim,
}}
>
<Text>Animating...</Text>
</Animated.View>
</View>
);
};

export default MyComponent;

Key Points in the Example:


Animated.timing : We start an animation (fading in the view).

: The API call is deferred and only


InteractionManager.runAfterInteractions()

executed after the animation finishes. This ensures that the animation runs
smoothly without being blocked by the API call.

fetchDataFromAPI : This function handles the API request, but it won’t run until
all animations or user interactions are completed.

Version 34
When to Use InteractionManager?
Heavy computations: If you’re performing CPU-intensive tasks, like
complex calculations, and you want to avoid blocking the UI.

API calls: If you need to make network requests but don’t want them to
interfere with animations or interactions.

Heavy data processing: When you need to process large datasets but don’t
want it to impact user experience.

Conclusion:
InteractionManager helps in managing tasks that would normally block the UI
thread, making sure that your animations and UI remain smooth and
responsive. It’s particularly useful in scenarios where you have animations and
heavy tasks running in parallel.
Would you like further insights on other performance optimization strategies in
React Native?

Answer for the Question on Presentation and Container


Components:
The distinction between Presentation (Dumb) Components and Container
(Smart) Components is crucial for creating a scalable and maintainable React
Native application. Here's how I would approach the answer:

Presentation (Dumb) Components:


1. Purpose:
Presentation Components are responsible for displaying the UI. They are
stateless, receive props, and are generally pure (do not manage their own
state or logic).

2. Benefits:

Reusability: Since Presentation Components only focus on rendering


and are isolated from the app’s state management, you can reuse them
across multiple parts of your app without worrying about side effects.

Separation of Concerns: They focus solely on UI rendering, making


them easier to maintain and test.

Version 35
Design Consistency: Since these components are reusable, you ensure
consistent UI throughout the application. For example, if you have a
button component, you can use it everywhere in your app. If you need
to change its style (e.g., change the color from blue to red), you only
need to do it in one place.

Example:

const Button = ({ color, onClick, label }) => {


return (
<button style={{ backgroundColor: color }} onClick=
{onClick}>
{label}
</button>
);
};

Container (Smart) Components:


1. Purpose:
Container Components are responsible for managing state and handling
logic. They often contain stateful logic and interact with data sources or
perform operations.

2. Benefits:

Logic Handling: Container Components handle business logic (e.g.,


fetching data, updating state, or managing user interactions) and pass
data to Presentation Components via props.

UI Composition: They combine multiple Presentation Components to


compose the UI and control the flow of data between them.

Example:

const Container = () => {


const [count, setCount] = useState(0);

const increment = () => setCount(count + 1);


const decrement = () => setCount(count - 1);

Version 36
return (
<div>
<Button color="blue" onClick={increment} label="In
crease" />
<Button color="blue" onClick={decrement} label="De
crease" />
</div>
);
};

Answer for the Button Re-rendering Question:


The issue you're describing seems to be related to React's reconciliation
process and state updates. In a typical case, if two buttons are using the same
component but with different functionality (e.g., one for increasing salary and
one for decreasing salary), both buttons will indeed re-render when the state
updates. However, this can be optimized.

1. Key Problem:
If both buttons are part of the same component and you only want the
button related to the salary to re-render when it is clicked, you need to
make sure that the components are properly isolated and optimized. React
will re-render all components that use the state that has changed.

2. Solution: Using React Memoization and Component Isolation:

React.memo() : You can wrap the button component with React.memo() to


memoize the component, so it only re-renders if the props change. This
helps avoid unnecessary re-renders when other parts of the state
change.

Component Isolation: Ensure that state management is scoped


correctly, so that changing one button’s state does not cause
unnecessary re-renders of other buttons.

Example with React.memo() :

const Button = React.memo(({ color, onClick, label }) =>


{
console.log(`${label} button rendered`);
return (

Version 37
<button style={{ backgroundColor: color }} onClick=
{onClick}>
{label}
</button>
);
});

const Container = () => {


const [salary, setSalary] = useState(1000);
const [counter, setCounter] = useState(0);

return (
<div>
<Button color="blue" onClick={() => setSalary(sala
ry + 100)} label="Increase Salary" />
<Button color="green" onClick={() => setSalary(sal
ary - 100)} label="Decrease Salary" />
<Button color="blue" onClick={() => setCounter(cou
nter + 1)} label="Increase Counter" />
</div>
);
};

3. Key Takeaways:

Use React.memo() or useMemo() when components are highly dependent


on props to prevent unnecessary re-renders.

Break down the state into smaller components, and use separate states
for different parts of the UI that don’t need to interact.

Mistakes to Avoid in Your Answer:


1. Avoid Confusing Container and Presentational Components:

Container Components handle business logic and state, while


Presentation Components handle the UI rendering. Never mix them up
in your explanation, as this is a common mistake in interviews.

2. Don’t Overcomplicate the Explanation:

Version 38
Keep the answer simple and focused. Don’t go into unnecessary details
unless asked. Explain the core difference in terms of state
management and UI rendering.

3. Be Clear on Optimization Techniques:

If asked about re-rendering issues (like the button re-rendering), ensure


that you discuss the role of memoization and state isolation clearly. It’s
common for developers to forget about React’s optimizations like
React.memo() or useMemo() , which can greatly improve performance in
such cases.

Summary:
Presentation Components = Stateless, reusable, focused only on UI.

Container Components = State-driven, responsible for business logic and


managing child components.

For re-rendering issues, use React.memo() to optimize unnecessary renders.

If you follow this approach, your response will be clear, structured, and
demonstrate good understanding of React principles. Would you like further
clarification on any of these concepts?

Answer on AsyncStorage in React Native:


AsyncStorage is a key-value store in React Native, used for storing data locally
on the device in a persistent way. It’s commonly used to save small amounts
of data that should persist between app sessions, like user preferences or
application settings.

Key Points about AsyncStorage:


1. Persistent Storage:
AsyncStorage allows you to store data that persists even after the app is
closed or the device is restarted. This makes it useful for storing small
pieces of information, such as settings, flags, or lightweight user data.

2. Key-Value Pair:
Data in AsyncStorage is stored as a key-value pair, making it easy to
retrieve and set values based on keys.

3. Non-Secure:

Version 39
One important thing to note is that AsyncStorage is not encrypted,
meaning that the data stored in it is not secure and can be accessed by
someone with the necessary tools, especially if the device is compromised.

When to Use AsyncStorage:


Non-sensitive data: AsyncStorage is ideal for storing non-sensitive data
that needs to persist across app sessions. Examples include:

App settings (like theme or language preferences)

Flags or states (like whether the user has completed onboarding)

Caching small data (like some previously fetched data)

When NOT to Use AsyncStorage:


Sensitive Data: AsyncStorage should not be used for sensitive information
such as:

This is because AsyncStorage does not provide encryption or any form of


secure storage. If you need to store sensitive data, use a
secure storage solution like EncryptedStorage or Keychain on iOS and
Keystore on Android.

Authentication tokens (access tokens, refresh tokens)

Personal user data (e.g., passwords)

Financial or health-related data

Example of Using AsyncStorage:

import AsyncStorage from '@react-native-async-storage/async


-storage';

// Save data
const saveData = async () => {
try {
await AsyncStorage.setItem('@user_token', 'some_token_v
alue');
console.log('Token saved!');
} catch (error) {
console.error('Failed to save token', error);

Version 40
}
};

// Retrieve data
const getData = async () => {
try {
const token = await AsyncStorage.getItem('@user_toke
n');
if (token !== null) {
console.log('Token:', token);
}
} catch (error) {
console.error('Failed to retrieve token', error);
}
};

// Remove data
const removeData = async () => {
try {
await AsyncStorage.removeItem('@user_token');
console.log('Token removed!');
} catch (error) {
console.error('Failed to remove token', error);
}
};

Important Notes:
1. Limitations: AsyncStorage is not ideal for storing large data sets. For larger
datasets, SQLite or Realm is a better option.

2. Data Retrieval: AsyncStorage is asynchronous, so use async/await or


Promise to handle the data retrieval and saving operations.

3. Not for Sensitive Data: As mentioned, avoid using AsyncStorage for secure
or private information. Use SecureStorage for encrypting sensitive data
before storing it.

Mistakes to Avoid:

Version 41
Using AsyncStorage for Secure Data: Don’t store sensitive data like
tokens, credentials, or personal information in AsyncStorage.

Not Handling Errors: Always handle errors (e.g., using try/catch) when
interacting with AsyncStorage, as operations might fail due to various
reasons (e.g., device storage full, app permissions, etc.).

Ignoring Async Nature: AsyncStorage is asynchronous, so not handling it


properly with async/await can lead to unpredictable behavior, like accessing
data before it's been written.

Conclusion:
AsyncStorage is great for storing small, non-sensitive pieces of data
persistently across app sessions.

For sensitive data, always use secure storage solutions to protect user
data.

This approach ensures that you’re using the right storage system for different
types of data and optimizing both security and performance for your app.
Would you like to dive deeper into other secure storage options for React
Native?

Explanation of Set Native Props in React Native:


setNativeProps is a method in React Native that allows you to bypass React’s
rendering process and directly update the properties of a native view (like a
View , Text , Image , etc.) without causing a re-render of the entire React

component tree.

How setNativeProps Works:


Normally, when you update the state in a React component, React re-renders
the component and any of its child components that depend on the state. This
re-render process involves calculating the diffing algorithm, which is
expensive for large component trees or frequent updates (such as during
animations).
However, setNativeProps allows you to directly interact with the native view and
update properties without going through the React reconciliation process. This
means the properties of the view are modified directly at the native level,
skipping the re-render of the React component tree.

Version 42
Why setNativeProps is Useful:
This method is particularly useful in scenarios where you need to perform high-
frequency updates, such as during animations, gesture handling, or when
you're dealing with large lists of components (for example, 30 components as
you mentioned) and you want to avoid unnecessary re-renders.

In your case, where you want to animate a specific component (say, a button or
a box) without triggering re-renders of other components on the screen, using
setNativePropscan significantly improve performance by updating only the
native properties of that component without touching the rest of the UI.

Example of setNativeProps Usage:

import React, { useRef } from 'react';


import { View, Text, Animated } from 'react-native';

const MyComponent = () => {


const animatedValue = useRef(new Animated.Value(0)).curre
nt;

const startAnimation = () => {


Animated.timing(animatedValue, {
toValue: 100,
duration: 1000,
useNativeDriver: true,
}).start();
};

const boxStyle = {
transform: [{ translateX: animatedValue }],
};

return (
<View>
<Text>My Animating Box</Text>
<Animated.View
style={[{ width: 100, height: 100, backgroundColor:
'blue' }, boxStyle]}
// Using setNativeProps to directly manipulate nati

Version 43
ve properties
ref={(ref) => ref && ref.setNativeProps({ style: {
backgroundColor: 'green' } })}
/>
<Button onPress={startAnimation} title="Start Animati
on" />
</View>
);
};

In this example, the setNativeProps method is used to directly change the style

of the Animated.View without causing a re-render. This can be especially useful


in cases where you need to change certain visual properties on the native level
without going through React’s diffing process.

Performance Implications:
1. Avoids Re-rendering:
The primary benefit of using setNativeProps is that it avoids re-rendering the
component and its children. React does not need to go through its diffing
and reconciliation process, which can be costly in terms of performance,
especially with complex UI trees or frequent updates.

2. Improved Performance During Animations:


In animation-heavy scenarios (like your example of having 30 components
on the screen), using setNativeProps ensures that only the animated
components are updated, not the entire screen. This avoids unnecessary
work and makes animations smoother.

3. Low-Level Updates:
By directly updating native properties, setNativeProps allows React Native to
perform lower-level optimizations at the native side, which are faster than
React’s JavaScript-based approach to updating the UI.

Caveats and Considerations:


1. Use Sparingly:
While setNativeProps can be a performance booster in certain scenarios, it
bypasses React’s lifecycle and does not trigger the component update
cycle. This can lead to scenarios where React is unaware of changes to the

Version 44
UI. Therefore, it should be used sparingly and only when you have specific
performance concerns (e.g., during animations or gesture handling).

2. Limited React Features:


Since setNativeProps directly manipulates native views, it can limit React
features like props validation, state synchronization, or component
lifecycle methods. This means you need to ensure you're using it for non-
critical updates.

3. Not Ideal for All Use Cases:


While it’s great for certain performance optimizations, setNativeProps is not a
solution for most scenarios in React Native. It’s best reserved for cases
where performance is critical, like animations or high-frequency updates.

4. Error-Prone:
Since setNativeProps bypasses React’s normal flow, it can potentially lead to
bugs or inconsistencies, especially if the component state or props are not
correctly managed. Always ensure that the UI updates are well-controlled
to avoid UI mismatches.

Mistakes to Avoid:
Overuse: Relying too much on setNativeProps can lead to uncontrolled
components, making debugging more difficult.

Inconsistent State: Since setNativeProps does not trigger a re-render, it can


cause state inconsistencies if used incorrectly. Make sure that the view
state is kept in sync with the underlying props.

Not Using useNativeDriver : When performing animations, always prefer using


useNativeDriver to offload animations to the native thread, which can further
improve performance, especially in combination with setNativeProps .

Conclusion:
is an excellent tool for optimizing performance, especially in
setNativeProps

scenarios where frequent UI updates (like animations) are required. By directly


updating native views and avoiding re-renders, it helps in smoothing out
animations and reducing the load on the JavaScript thread. However, it should
be used judiciously to avoid bypassing important React features, such as
component lifecycle management and state synchronization.

Version 45
Would you like further details or examples on using setNativeProps effectively in
specific scenarios?
Answer on setNativeProps Usage for Animation:
If you have a screen with 30 components and you want to perform an
animation (e.g., translate or scale a particular component), using setNativeProps
will prevent the entire screen from re-rendering. Instead, it directly updates
the native view without affecting the React component tree. This means only
the animated component will update, and performance improves because
React does not re-render the whole UI.

Example:
Scenario: You have 30 components on the screen.

Goal: Perform an animation on one of those components (e.g., moving a


button).

Solution: Use setNativeProps to directly modify the animated component's


properties (e.g., position or color) without causing the re-render of all 30
components.

Thank you for the clarification. Here's how you can frame the answer with a
quick and effective explanation, followed by a highlighted example for easy
recall:

Answer on Best Way to Debug React Native Applications:


There are several ways to debug React Native apps, depending on your
preference and the debugging context:

1. Console.log:

The simplest method for logging values, tracking variables, and


understanding flow. It's basic but effective for small-scale debugging.

2. Chrome Debugger:

Use Chrome DevTools to perform line-by-line debugging.

You can inspect state, variables, and network requests, giving you a
comprehensive view of what's happening in the app.

3. Xcode and Android Studio for Performance Profiling:

Version 46
If you want to debug performance issues like memory consumption,
CPU usage, or network traffic, these tools are best suited for profiling.

They help in identifying bottlenecks in the app, including memory


leaks, excessive CPU usage, and more.

Quick Example for Easy Recall:


Scenario 1: Simple Issue – For tracking a variable value or flow, use
console.log to print out the data and check.

Scenario 2: In-depth Debugging – If you need to debug code line-by-line,


use Chrome DevTools to step through your React Native code and inspect
values.

Scenario 3: Performance Issue – For things like high memory usage or


CPU spikes, use Xcode or Android Studio to profile and identify
performance issues.

What Should Be Satisfying for the Interviewer:


1. Clear and Concise Explanation: The answer should cover different tools for
different levels of debugging – simple logging (console.log), debugging
code (Chrome DevTools), and performance profiling (Xcode/Android
Studio).

2. Contextual Understanding: It's important to show awareness of when each


tool should be used based on the problem at hand – whether it's a simple
bug or performance issue.

3. Real-World Application: A good answer would demonstrate an


understanding of why certain tools are suited for specific debugging
scenarios. It should reflect practical experience in debugging React Native
apps.

4. Examples: Offering a real-world example or quick scenario helps the


interviewer understand your thought process. For instance, explaining how
you would debug a performance bottleneck using Android Studio is more
convincing than just listing tools.

Mistakes to Avoid in Answering:

Version 47
1. Over-explaining Basic Tools: Don’t spend too much time on very basic
tools like console.log unless the interviewer asks for it.

2. Ignoring Performance Profiling: If you're solely focused on debugging


code without touching on performance debugging, it might show a gap in
your experience with real-world app performance issues.

3. Being Vague: Simply mentioning tools without explaining when and why
you would use them can lead to a lack of clarity.

Is Jest Used for Debugging Real-Node Applications?


Jest is not primarily used for debugging, but rather for automated testing. It is
a JavaScript testing framework used to ensure that your code is functioning as
expected through various tests like unit tests, integration tests, and snapshot
tests.
While Jest is not a debugging tool, it can indirectly help you catch bugs by
running tests that validate whether your code behaves as intended. However, it
does not allow you to inspect or step through your code like traditional
debugging tools do.

Key Differences Between Jest and Debugging Tools:


Jest:

Used for automated testing (unit, integration, and snapshot tests).

Helps catch bugs by testing your code before you run it.

Does not allow you to debug (no real-time inspection or code


stepping).

Debugging Tools (Chrome Debugger, Xcode, Android Studio):

Used to inspect, step through, and analyze code in real-time during


execution.

Helps you find and fix issues during runtime by directly interacting with
the code.

Version 48
Offers breakpoints and real-time analysis of your app’s state and
behavior.

Quick Example for Easy Recall:


Jest Testing:

Used to ensure your code logic works by running automated tests.

Example: Testing a function using Jest to verify it returns the correct


result.

// simpleFunction.js
export const add = (a, b) => a + b;

// simpleFunction.test.js
import { add } from './simpleFunction';

test('adds 1 + 2 to equal 3', () => {


expect(add(1, 2)).toBe(3);
});

Debugging with Chrome Debugger:

Used to step through code and inspect values at runtime.

Example: Setting a breakpoint in the code to check the value of a


variable during app execution.

Conclusion:
Jest is used for automated testing and helps you identify bugs by running
tests on your code, but it is not a tool for debugging.

For debugging real-node applications, you would use tools like Chrome
Debugger, Xcode, or Android Studio, which allow you to inspect and
modify your code during execution.

This combined explanation should help clarify the distinction between Jest and
debugging tools and how both serve different purposes.

Version 49
Best Practices for Testing React Native Applications:
Testing in React Native should follow a structured approach to ensure the
reliability of the application throughout the development process. Below is a
breakdown of best practices and testing tools:

Best Practices for Testing React Native Apps:


1. Unit Testing:

Purpose: To test individual components or functions to ensure they


behave as expected.

Best Practice: Write tests for small units of functionality like functions
or components. Each test should be isolated from others to check that
specific functionality independently.

Example: Testing a function that formats the date correctly.

2. Integration Testing:

Purpose: To test if different modules or components work together


correctly.

Best Practice: Test the interaction between units (e.g., a component


with an API call). This ensures that a component integrates seamlessly
into the broader application.

Example: Testing the integration of a login form with an authentication


API.

3. UI Testing:

Purpose: To test how the UI components behave and how the user
interacts with them.

Best Practice: Use tools like Jest and React Native Testing Library to
automate UI interaction tests such as button clicks, form submissions,
and UI rendering.

Example: Testing if a button triggers an API call when clicked.

4. Mocking:

Version 50
Purpose: To simulate external dependencies (e.g., API calls) for unit
testing without actually performing the real operation.

Best Practice: Use mock functions or libraries like jest.mock() to


simulate these dependencies and isolate your code.

Example: Mocking API responses during unit tests to test how


components react to different data.

5. Snapshot Testing:

Purpose: To ensure that the UI doesn't change unexpectedly.

Best Practice: Take snapshots of the rendered UI and compare them


over time to detect any unintended changes.

Example: Testing a component's rendering by saving a snapshot and


comparing it in future runs.

Testing Tools You Can Use in React Native:


1. Jest:

Primary Tool for unit testing in React Native.

Allows you to write unit tests, mock APIs, and even run UI tests.

Jest also supports snapshot testing for UI consistency.

Example:

// Function to test
export const add = (a, b) => a + b;

// Jest unit test


test('adds 1 + 2 to equal 3', () => {
expect(add(1, 2)).toBe(3);
});

2. React Native Testing Library:

Used for testing React Native components.

Focuses on interacting with components like a user would, rather than


testing implementation details.

Version 51
Example:

import { render, fireEvent } from '@testing-library/reac


t-native';
import Button from '../Button'; // hypothetical button c
omponent

test('Button press triggers an action', () => {


const { getByText } = render(<Button onPress={mockFunc
tion}>Press Me</Button>);
fireEvent.press(getByText('Press Me'));
expect(mockFunction).toHaveBeenCalledTimes(1);
});

3. Detox:

End-to-End (E2E) testing framework for React Native.

Useful for testing the full application flow, ensuring features work as
expected when interacting with the UI.

Example:

describe('Login Screen', () => {


it('should login successfully', async () => {
await element(by.id('username')).typeText('user');
await element(by.id('password')).typeText('passwor
d');
await element(by.id('loginButton')).tap();
await expect(element(by.id('welcomeMessage'))).toBeV
isible();
});
});

4. Cypress (For Web apps, but can be useful for cross-platform projects):

A web testing framework that can also be used for testing cross-
platform components like React Native Web.

Answer Example for the Interviewer:

Version 52
Q: How do you test React Native applications?
In React Native development, I follow a structured approach to testing, starting
with unit tests and moving on to integration tests and UI testing:

1. Unit Testing: First, I write unit tests for small units of functionality like
functions or components. I use Jest to test functions and methods for
expected behavior, making sure individual components or logic are working
in isolation.

2. Integration Testing: Once I ensure the components are working correctly in


isolation, I perform integration testing to check if different parts of the app
work well together. For example, I test how components communicate with
APIs or how they render combined states.

3. UI Testing: After integration, I focus on UI testing. This is where I automate


the testing of user interactions using tools like Jest and React Native
Testing Library. I test whether the UI responds correctly to user input, such
as button presses and form submissions.

4. Business Logic & UI Test Cases: I write test cases for business logic to
ensure calculations or API calls work correctly. For the UI, I focus on
making sure that components render as expected under different
conditions.

Tools I Use:
Jest for unit testing and mocking API calls.

React Native Testing Library for UI testing and simulating user


interactions.

Detox for end-to-end testing (E2E) when testing full app flows, like logging
in or completing a transaction.

Mistakes to Avoid:
1. Skipping Test Coverage: Don't skip writing unit or integration tests as they
are crucial for ensuring the correctness of your code before moving on to
other stages of development.

2. Testing Only Happy Paths: Make sure to test edge cases and error
handling scenarios, not just the typical use cases.

Version 53
3. Not Automating Tests: Manually running tests is time-consuming and
prone to error. Always aim to automate your tests as much as possible.

4. Mixing Test Types: Keep unit tests, integration tests, and UI tests distinct.
Unit tests should test isolated logic, integration tests should test how
components work together, and UI tests should simulate user interactions.

By following these practices and using the right tools, you can ensure a reliable
and bug-free React Native application.

Investigation Steps for App Crashing During Scrolling:


When an app with a lot of images or content crashes while scrolling, it usually
points to issues with memory consumption or processor load. To identify and
fix these issues, we can follow a systematic approach.

Step-by-Step Process to Investigate:


1. Identify the Symptoms:

The app crashes after scrolling for some time.

Memory consumption increases over time (without being released


properly).

CPU usage spikes during scrolling or when images are loading.

2. Check for Memory Leaks:

The most common reason for crashes in such scenarios is memory


leaks.

Use the Profiler in Xcode or Android Studio to monitor memory usage


while scrolling.

In Xcode: Use the Memory Debugging Tool to monitor memory


consumption.

In Android Studio: Use Android Profiler to check for memory usage


and leaks.

As you scroll through the app, check if memory usage increases


continuously without dropping, even when off-screen images are no
longer visible.

3. Investigate Image Loading:

Version 54
Image loading issues could be consuming too much memory. If images
are not properly released, they may pile up in memory.

FlatList in React Native is more efficient for handling large lists of data,
especially images.

Why FlatList is Important: FlatList only renders visible items and


offloads those that are out of view, helping to manage memory
better.

If you're using a regular ScrollView , it might be loading all the images


at once, which can lead to excessive memory usage.

Solution: Switch to FlatList for rendering images, ensuring only the


items visible on the screen are loaded into memory.

4. Check Image Size and Optimization:

Large images can increase both memory usage and loading times,
making the app slow.

Ensure that the images are optimized before they are sent from the
server:

Resize images to match the device’s resolution (don’t load


unnecessarily large images).

Compress images to reduce file size without sacrificing too much


quality.

Implement Image Caching: Use caching libraries like react-native-


fast-image or react-native-cached-image to avoid reloading images
every time. Once an image is loaded, it should be cached and used
from memory or disk.

5. Optimize Performance with Lazy Loading:

Implement lazy loading for images. This ensures that images are
loaded only when they come into view.

Use the onEndReached prop in FlatList to trigger loading of more


images as the user scrolls, but do not preload all of them at once.

6. Check for CPU Usage and Bottlenecks:

Monitor the CPU usage during scrolling to see if the processor is being
overloaded.

Version 55
If you notice a spike in CPU usage, there could be an inefficient
algorithm running during the scroll. Check the event handlers,
animations, or image processing logic that might be consuming
unnecessary CPU resources.

Optimize animations or heavy operations to run asynchronously or


offload them to background threads.

Example Solution and Best Practices:

1. Switch to FlatList:

import { FlatList } from 'react-native';

const renderItem = ({ item }) => (


<Image source={{ uri: item.uri }} style={{ width: 100, he
ight: 100 }} />
);

const MyImageList = ({ data }) => {


return (
<FlatList
data={data}
renderItem={renderItem}
keyExtractor={(item) => item.id.toString()}
initialNumToRender={10} // Render only 10 items initi
ally
maxToRenderPerBatch={5} // Limit the number of items
rendered per batch
windowSize={5} // Number of items to keep in memory
at once
/>
);
};

2. Optimize Image Loading:


Use image resizing and compression before sending images from the
server.

Version 56
Use react-native-fast-image for faster image loading and caching:

import FastImage from 'react-native-fast-image';

const MyImageComponent = ({ uri }) => (


<FastImage
style={{ width: 100, height: 100 }}
source={{
uri: uri,
priority: FastImage.priority.normal,
}}
resizeMode={FastImage.resizeMode.cover}
/>
);

3. Implement Image Caching:


Cache images to avoid reloading them each time. Libraries like react-
native-cached-image can help:

import CachedImage from 'react-native-cached-image';

const CachedImageComponent = ({ uri }) => (


<CachedImage
source={{ uri }}
style={{ width: 100, height: 100 }}
resizeMode="contain"
/>
);

4. Monitor and Optimize:


Use React Native Debugger to monitor network requests, image loading,
and memory consumption.

In Xcode, use the Memory Leak Detector to check if any memory is being
leaked.

Conclusion:

Version 57
By following these steps, we can effectively reduce memory consumption and
optimize performance while scrolling through large lists in React Native. The
key action points are:

Use FlatList instead of ScrollView to load only visible items.

Optimize and cache images to reduce memory usage.

Monitor memory and CPU usage with Xcode and Android Studio.

These steps should prevent the app from crashing due to memory or
performance bottlenecks.

Answer to Interviewer’s Question: Where Should We Save the


Cache in React Native?
When dealing with caching in React Native applications, the choice of where to
store the cache and which method to use depends on the nature of the data
you're caching (images, network responses, etc.) and how you want to manage
the cache over time.

1. Using Third-Party Libraries:


There are several third-party libraries available that provide caching
functionality out of the box. These libraries take care of caching, managing the
storage location, and clearing the cache when necessary.

Popular Libraries for Caching:


1. React Native Fast Image (for Image Caching):

Purpose: Primarily used for caching images.

Cache Location: It stores images in the device's cache directory,


allowing images to be loaded quickly without needing to be re-
downloaded.

Example:

import FastImage from 'react-native-fast-image';

const MyImageComponent = ({ uri }) => (


<FastImage
style={{ width: 100, height: 100 }}
source={{

Version 58
uri: uri,
priority: FastImage.priority.normal,
}}
resizeMode={FastImage.resizeMode.cover}
/>
);

2. React Native Async Storage (for Small Data Caching):

Purpose: AsyncStorage allows you to store small pieces of data (such


as user preferences, tokens, etc.) persistently. While it's not designed
specifically for caching large objects like images, it can be used for
small cache-like functionality.

Cache Location: AsyncStorage stores data in the device's local storage


(on disk), which is persistent but not encrypted by default.

Example:

import AsyncStorage from '@react-native-async-storag


e/async-storage';

const saveDataToCache = async (key, value) => {


try {
await AsyncStorage.setItem(key, value);
} catch (e) {
console.error("Error saving data to cache", e);
}
};

const getDataFromCache = async (key) => {


try {
const value = await AsyncStorage.getItem(key);
if (value !== null) {
return value;
}
} catch (e) {
console.error("Error retrieving data from cache",
e);

Version 59
}
};

3. React Native Cached Image (for Image Caching):

Purpose: Another library dedicated to caching images.

Cache Location: It can store images in the app's cache directory and
provides tools to manage caching behaviors such as clearing the
cache, fetching images from the cache, etc.

Example:

import CachedImage from 'react-native-cached-image';

const MyImageComponent = ({ uri }) => (


<CachedImage
source={{ uri }}
style={{ width: 100, height: 100 }}
resizeMode="contain"
/>
);

4. react-native-fs (for File Caching):

Purpose: Allows for caching data in the form of files on the device.

Cache Location: Data is stored in the device's file system, which allows
for caching large objects (like files or images) that you can manage
yourself.

Example:

import RNFS from 'react-native-fs';

const cacheImage = async (uri) => {


const filePath = `${RNFS.CachesDirectoryPath}/imag
e.jpg`;
await RNFS.downloadFile({ fromUrl: uri, toFile: fil
ePath }).promise;
};

Version 60
const getCachedImage = async () => {
const filePath = `${RNFS.CachesDirectoryPath}/imag
e.jpg`;
const exists = await RNFS.exists(filePath);
if (exists) {
return filePath;
}
};

2. Implementing Cache Yourself:


If you prefer not to use third-party libraries, you can implement caching
mechanisms yourself using local file storage or local databases.

Using File System for Caching (e.g., react-native-fs):


Pros: Full control over cache management. You can decide where and how
to store the data.

Cons: More complex implementation. You need to handle cache expiration


and cleaning up old data.

Store the cached images or files in the device's Caches directory. This
directory is intended for storing temporary files that can be cleared at any
time by the system if the device runs low on space.

Using SQLite or Local Databases:


Pros: Useful for caching structured data (e.g., network responses, lists).

Cons: Requires more setup and management.

SQLite databases can be used to store small data in tables with structured
queries. For more complex or persistent caching, this can be a good choice.

Example of File Caching with React Native File System (react-


native-fs):

import RNFS from 'react-native-fs';

// Save a file to cache directory


const saveToCache = async (fileName, data) => {

Version 61
const path = `${RNFS.CachesDirectoryPath}/${fileName}`;
await RNFS.writeFile(path, data, 'utf8');
};

// Get a cached file


const getFromCache = async (fileName) => {
const path = `${RNFS.CachesDirectoryPath}/${fileName}`;
const exists = await RNFS.exists(path);
if (exists) {
return await RNFS.readFile(path, 'utf8');
}
};

Where Should We Save the Cache?


For images: Use libraries like react-native-fast-image or react-native-
cached-image, which automatically handle cache storage in the app's
cache directory.

For small data (such as user settings, tokens, etc.): Use AsyncStorage,
which saves data in the device's local storage.

For larger files or more complex data: Use react-native-fs to save files in
the Caches directory or implement a custom caching strategy based on
SQLite.

Important Considerations:
Always monitor your app’s memory consumption when caching images or
files, especially for large data.

Clear old cache periodically to avoid excessive storage usage.

Ensure security for sensitive data like tokens (use react-native-


encrypted-storage for secure storage instead of AsyncStorage).

By following these best practices, you can manage your app’s cache effectively
while ensuring good performance and efficient memory use.
In React Native, cache clearing depends on your app's design and the specific
data you're caching. By default, when you use third-party libraries like react-
native-fast-image or react-native-cached-image , they handle cache management for

Version 62
you. However, there are cases where you might need to implement cache
clearing manually to improve performance or handle storage issues.

1. Do We Need to Clear Cache Internally in React Native?


Yes, clearing cache is important, especially when dealing with large files,
images, or network responses that consume memory.

React Native doesn’t automatically clear cache unless a specific caching


library does so. Therefore, it’s a good practice to implement cache
management strategies, such as clearing outdated or unused cache,
especially if you’re storing data locally (like images, tokens, or large files).

2. When Should You Clear Cache Internally?


Memory management: If your app has large amounts of data being cached
(e.g., images, files), you should manage memory by clearing the cache at
appropriate times. For example, when the user logs out or when certain
data is no longer needed.

Performance optimization: If you notice performance degradation due to


excessive cached data, clear it periodically.

3. How to Implement Cache Clearing in React Native?


For Image Caching: Some libraries like react-native-fast-image allow you to
clear the cache programmatically.
Example with react-native-fast-image :

import FastImage from 'react-native-fast-image';

// Clear the cache for all images


FastImage.clearMemoryCache();
FastImage.clearDiskCache();

For File Caching: If you're using react-native-fs to cache files, you can
delete the cached files manually.
Example with react-native-fs :

import RNFS from 'react-native-fs';

Version 63
const clearCache = async () => {
const cachePath = `${RNFS.CachesDirectoryPath}/image.j
pg`;
const exists = await RNFS.exists(cachePath);
if (exists) {
await RNFS.unlink(cachePath); // Delete cached imag
e
}
};

For AsyncStorage: You can clear specific keys or clear all cached data in
AsyncStorage.
Example:

import AsyncStorage from '@react-native-async-storage/as


ync-storage';

// Clear a specific item from AsyncStorage


await AsyncStorage.removeItem('key');

// Clear all items from AsyncStorage


await AsyncStorage.clear();

4. Should Users Clear the Cache Manually?


No, as a general rule, it’s not recommended to rely on users manually
clearing the cache. Instead, implement automatic cache clearing strategies
in your app.

Users clearing cache manually should be a last resort. If users need to clear
cache due to app issues (e.g., app slowdown or corrupted data), your app
may not be managing the cache effectively. Therefore, automatic clearing
and cleanup should be the preferred approach.

Summary:
In React Native, cache should generally be managed by the app, and you
should implement a strategy for clearing outdated or unnecessary cache.

Version 64
Manual cache clearing (by the user) should be avoided if possible, and
caching should be done efficiently to prevent issues like performance
degradation or storage overuse.

By implementing internal cache management and cleanup, you ensure your app
runs efficiently and provides a better user experience without requiring users to
manually clear cache.

Sure! Let's break down the answer and the key points related to performance
issues in React Native, and I'll clarify the part about arrow functions and
normal functions as well.

Main Performance Issues in React Native (Based on the


interview response):
1. Single Thread for UI Rendering:

React Native relies on a single thread (the main thread) for UI


rendering. If this thread is blocked by heavy tasks like animations or
calculations (for example, calculating height or width during a render), it
can cause the application to slow down.

This is why you often want to offload heavy tasks to a background


thread or avoid running them on the main thread to prevent UI freezes.

2. Arrow Functions and Re-renders:

Arrow functions can cause performance overhead if they are defined


inline within render methods.

Every time the component re-renders, new instances of those arrow


functions are created, even if the logic hasn't changed. This causes
unnecessary re-renders of the components that rely on them, leading to
performance degradation.

In React, passing inline functions like arrow functions causes props to


change on every render, triggering unnecessary re-renders of child
components.

3. Inline Styling vs. StyleSheet:

Inline styling can also cause performance problems because it creates


new objects on each render. So, every time React re-renders the

Version 65
component, a new styling object is created, leading to unnecessary
memory allocations.

StyleSheet.create should be used instead of inline styling. This creates


a static reference to the style, and React Native can use this reference
for subsequent renders, avoiding re-creation of style objects on each
render.

What Happens If You Use a Normal Function Instead of an


Arrow Function?
If you use a normal function (regular function declaration) instead of an
arrow function, it does not re-create the function instance on every render.

Arrow Function:

When you use an arrow function inside the render method, React
creates a new function every time the component re-renders. This
can trigger re-renders in child components if those functions are
passed as props.

Normal Function:

A normal function declared outside of the render method or in the


component's class body will only be created once (or once per
instance of the component). This is more efficient than defining an
arrow function inline because React doesn't need to re-create the
function on each re-render.

Example: Arrow Function vs. Normal Function

// Arrow function (inline function)


const MyComponent = () => {
const handleClick = () => {
console.log('Button clicked');
};
return <Button onPress={handleClick} />;
};

// Normal function (declared outside the render method)


const MyComponent = () => {
const handleClick = MyComponent.handleClick;

Version 66
return <Button onPress={handleClick} />;
};

MyComponent.handleClick = () => {
console.log('Button clicked');
};

In the first example ( handleClick is an arrow function), every render creates


a new instance of the function.

In the second example ( handleClick is a normal function), the function is


created once and reused, avoiding re-creation on every render.

Summary of What to Avoid for Better Performance:


1. Avoid inline arrow functions in the render method. Use regular functions
declared outside the render flow.

2. Avoid inline styling; instead, use StyleSheet.create to keep references static.

3. Offload heavy tasks to background threads when possible, and ensure


that UI rendering is not blocked by heavy calculations.

Key Takeaways:
Arrow functions inside render methods cause performance overhead due
to re-creation on every render.

Normal functions or functions defined outside the render method prevent


this issue by creating only one instance.

This can be crucial for optimizing large lists or complex components


where re-renders are frequent.

By following these practices, you can ensure that your React Native app
performs efficiently and doesn't run into unnecessary re-renders, memory
issues, or processor bottlenecks.

Understood! If I were the interviewer, here's how I would break down and
evaluate the answer based on what's acceptable or satisfiable, and what you

Version 67
can do to give a better response than the student who answered previously.

Evaluating the Answer from an Interviewer's Perspective (Me,


as the Interviewer):
1. Understanding of Performance Issues:

The student correctly identifies the main performance issue: React


Native uses a single thread for UI rendering, and this can slow down the
app if you perform heavy tasks (like calculations, animations) directly
on that thread.

This is a good start, but the explanation lacks specific solutions for
optimizing performance beyond general knowledge.

2. Arrow Functions and Performance:

The student mentions the issue with inline arrow functions, which is a
valid point. However, the explanation could be improved by:

Clearly explaining the problem (i.e., re-creating new instances on


each render).

Adding a clear example to show why using inline arrow functions


causes unnecessary re-renders in child components, and how it
impacts performance.

The student also mentions the difference between arrow functions


and normal functions, but the explanation is somewhat shallow.
Details about why normal functions are more performant (by not
recreating function instances) could be elaborated.

3. Inline Styling vs. StyleSheet.create :

The student mentions using StyleSheet.create instead of inline styling,


which is correct and important for performance.

However, they should have added more emphasis on how inline styles
cause re-creation of the style object on every render, which consumes
extra memory and processing power.

4. FlatList Example:

The student gives a solid practical example regarding FlatList, which is


a great solution to memory management and performance, especially
with large lists. This was a well-made observation.

Version 68
What I, as the Interviewer, Would Want to Hear (Better
Answer):
A more satisfying answer would be one that:

1. Clearly explains how re-renders happen due to inline functions, and how
reusing references (for functions and styles) can optimize performance.

2. Provides concrete examples of how to structure components and styles to


avoid unnecessary re-renders.

3. Uses real-world scenarios or framework-specific solutions like FlatList,


VirtualizedList, and using background threads for heavy tasks.

Here's an ideal response that would satisfy the interviewer:

Perfect Answer:

In React Native, the main performance bottleneck often


comes from the fact that UI rendering is handled on a single
thread. If we perform heavy tasks like animations or
calculations on the UI thread, it can block the rendering
process, causing a noticeable lag or crash due to memory or
processor overload.
One common issue I’ve encountered is using inline arrow
functions inside the render method. React Native will create
a new instance of the function every time the component
re-renders. This results in props changing on every render,
which triggers unnecessary re-renders in child components,
even if the logic hasn’t changed. For example:

// Inline arrow function inside render metho


d
const MyComponent = () => {
const handleClick = () => { console.log("C
licked!"); }; // A new instance created on e

Version 69
very render
return <Button onPress={handleClick} />;
};

This can be avoided by defining the function outside the


render flow:

// Define the function outside render


const handleClick = () => { console.log("Cli
cked!"); };
const MyComponent = () => {
return <Button onPress={handleClick} />;
};

By reusing the same function reference, React doesn’t need


to re-render unnecessarily, improving performance.

Additionally, inline styling can cause performance issues as


well because React creates a new style object every time
the component re-renders. This can be avoided by using
StyleSheet.create to create styles only once:

// Inline styling example (avoid this)


const MyComponent = () => {
return <View style={{ marginTop: 10, paddi
ng: 20 }} />;
};

// Use StyleSheet.create instead (better per


formance)
const styles = StyleSheet.create({

Version 70
container: {
marginTop: 10,
padding: 20,
},
});
const MyComponent = () => {
return <View style={styles.container} />;
};

This prevents unnecessary memory allocations on every


render.
For large lists, using FlatList instead of a regular ScrollView is
crucial. FlatList only renders the items that are visible on the
screen and unloads offscreen items, which helps
significantly with memory management.
If performance is still an issue even after optimizing with
FlatList, I'd consider optimizing image loading through
caching, reducing the image size, or using a library like
react-native-fast-image to handle caching and loading
asynchronously.

Finally, if the app performs tasks like heavy calculations or


background operations, offloading these to background
threads or using tools like InteractionManager to handle
non-UI tasks can prevent the UI thread from becoming
blocked.

Key Points You Should Focus On:


Arrow functions and inline functions: Re-create instances on every render.
Prefer normal functions or memoized functions ( useCallback or useMemo ) to
avoid unnecessary re-renders.

Version 71
Inline styling: Causes new style objects to be created on each render,
which can be avoided by using StyleSheet.create .

FlatList: Efficient rendering of large lists by rendering only the visible items
and unloading off-screen items.

Performance profiling tools: Use Xcode and Android Studio for analyzing
memory usage, processor consumption, and overall performance.

Background processing: Move heavy tasks to background threads to avoid


blocking the UI thread.

Conclusion:
In order to satisfy the interviewer, the answer needs to be detailed, technical,
and should include practical examples. Explaining the core issues and offering
specific solutions with references to tools or best practices like FlatList,
StyleSheet, and memoization will make your answer more complete and
showcase your deeper understanding of performance optimization in React
Native.
Here’s a structured breakdown of the key points and how you can present the
answer effectively for your React Native interview preparation:

Benefits of Using React Native for Building Mobile Apps:


1. Optimal Performance:

React Native provides optimal performance with native modules, giving


developers access to platform-specific APIs and improving efficiency.

2. Code Reusability:

A major advantage is the ability to reuse code across platforms


(Android and iOS), which reduces the development effort and time.

3. Large Developer Community:

React Native has a thriving open-source community that continuously


contributes, which makes finding solutions and resources easier.

4. Live and Hot Reloading:

The live/hot reloading feature allows developers to see changes in real-


time without rebuilding the entire app, improving development speed.

5. Simple User Interface:

Version 72
React Native simplifies the process of building responsive UI, offering
pre-built components and supporting UI consistency across platforms.

6. Support for Third-Party Plugins:

React Native supports third-party libraries and plugins, which can


extend app functionality without writing platform-specific code.

7. Modular Architecture:

React Native’s modular approach to programming divides functionality


into smaller, reusable components, making the codebase easier to
maintain and scale.

8. Ready-Made Solutions:

React Native provides access to a wide range of pre-built libraries and


solutions, saving development time and providing built-in
functionalities.

Hybrid Apps vs. Native Apps:


Hybrid Apps:

Combines web and native app characteristics, built with HTML, CSS,
and JavaScript, then wrapped into a native app container.

Advantages: Easier to develop and maintain for multiple platforms with


a single codebase.

Disadvantages: Performance is slower due to the reliance on the


browser’s engine, and native-like experience is not fully achieved.

Native Apps:

Built specifically for a platform (iOS or Android) using platform-specific


programming languages (e.g., Swift for iOS, Java for Android).

Advantages: Faster performance, full access to device hardware,


better user experience, and more flexibility.

Disadvantages: Higher development costs and more time-consuming


maintenance for multiple platforms.

What is React Native?

Version 73
React Native is a cross-platform mobile development framework that
allows developers to write code in JavaScript while producing apps that
use native UI components.

React Native allows you to build apps for both Android and iOS without
needing to learn Java or Swift.

It was developed by Facebook in 2015 and uses JavaScript Core runtime


along with Babel transformers for ES6+ compatibility.

Virtual DOM Explanation:


The Virtual DOM (VDOM) is a lightweight in-memory representation of the
real DOM.

Instead of directly manipulating the actual DOM (which can be slow), React
uses the VDOM to optimize updates by keeping the UI representation in
memory.

Reconciliation is the process where React compares the real DOM with the
virtual DOM and updates only the parts of the UI that have changed.

Manipulating the VDOM is faster because it’s like editing a blueprint before
applying it to the real structure.

Why This Answer is Effective for Interviewing:


Clear Explanation: The answer covers all major aspects of React Native,
from its benefits to its core concepts.

Technical Depth: It provides not only a theoretical explanation but also


examples of practical benefits (e.g., performance, community, code
reusability).

Real-World Context: You can further explain how these benefits play out in
real-world development scenarios, which will be helpful during your
interview.

Concise and to the Point: The answer is brief yet informative, ensuring that
you cover all important aspects without overwhelming the interviewer with
too much detail.

This approach will demonstrate your deep understanding of React Native in a


concise, easy-to-understand format for your interviews.

Version 74
Here’s a list of the most commonly used React Native libraries along with
some third-party libraries and their primary uses. This will help you get familiar
with the tools and packages that are widely used in React Native development.

Core React Native Libraries (Built-in):


1. React Navigation

Use: Handles navigation within the app.

Details: Allows stack, tab, and drawer navigation, and is widely used in
React Native apps for routing and navigation.

2. React Native Paper

Use: Provides Material Design components for React Native apps.

Details: Offers pre-built components like buttons, dialogs, text inputs,


and more, designed according to Google's Material Design guidelines.

3. React Native AsyncStorage

Use: Simple, asynchronous, persistent storage for data.

Details: Can be used to store user preferences or app state between


app restarts.

4. React Native Elements

Use: Provides a set of pre-designed UI components.

Details: Includes buttons, input fields, cards, sliders, etc. It simplifies UI


development by providing highly customizable components.

5. React Native Gesture Handler

Use: Handles gestures and touch events.

Details: It is essential for building complex interactions such as swiping,


dragging, and long presses.

6. React Native Reanimated

Use: Handles animations in React Native.

Details: Offers advanced animation capabilities with improved


performance compared to the built-in Animated library.

7. React Native Maps

Use: Displays interactive maps in a React Native app.

Version 75
Details: Integrates with Google Maps, Apple Maps, and other map
providers to show maps, markers, polygons, and other map features.

8. React Native Image Picker

Use: Allows users to pick images from the gallery or camera.

Details: Helps in picking images from the device's camera or photo


gallery and works across both Android and iOS.

9. React Native Device Info

Use: Fetches device-specific information.

Details: Useful for retrieving device details like model, operating system
version, device name, and more.

Popular Third-Party Libraries:


1. Axios

Use: HTTP client for making requests to APIs.

Details: A promise-based library used for sending requests, fetching


data from APIs, and handling responses.

2. Lottie for React Native

Use: Render animations in React Native.

Details: Allows you to render JSON-based animations created in After


Effects with Lottie. Great for adding complex animations to the app.

3. React Native Firebase

Use: Firebase integration in React Native apps.

Details: Provides full Firebase support for React Native apps, including
authentication, analytics, messaging, storage, and more.

4. React Native Push Notification

Use: Handles push notifications.

Details: Easily integrates push notification functionality into React


Native apps for both iOS and Android.

5. React Native Vector Icons

Use: Provides a collection of customizable vector icons.

Version 76
Details: Contains a large collection of icons from popular icon libraries
like FontAwesome, Ionicons, MaterialIcons, etc.

6. React Native WebView

Use: Embeds web content into the app.

Details: Lets you display web pages inside a native view in your app,
useful for embedding third-party content or web-based features.

7. React Native Local Storage (or Encrypted Storage)

Use: Securely stores sensitive data (tokens, passwords).

Details: Allows you to securely store and retrieve sensitive information


like user credentials using encryption.

8. React Native Camera

Use: Provides camera functionality in the app.

Details: Helps in integrating the camera to take photos or videos, with


support for various camera settings and features.

9. React Native Animatable

Use: Simplified animations for React Native.

Details: Allows you to easily create and apply animations to


components like fade, scale, rotate, etc.

10. React Native Share

Use: Share content across various platforms.

Details: Enables content sharing to third-party apps (like Facebook,


Twitter, etc.) via the native sharing dialog.

11. React Native Sound

Use: For handling sounds.

Details: Provides an API to play sound effects, background music, or


record audio. Useful for adding audio features to the app.

12. React Native Auth0

Use: Authentication and authorization.

Details: Simplifies implementing authentication using Auth0, a secure


identity management service.

Version 77
13. React Native Clipboard

Use: Handles clipboard functionality (copy/paste).

Details: Allows you to read from and write to the device's clipboard,
useful for copying and pasting data.

14. React Native Notification

Use: Create local notifications.

Details: Supports both push and local notifications for iOS and Android,
helping to send notifications at scheduled times or events.

Best Practices for Using Libraries:


1. Use Only What You Need:

Avoid overloading your app with too many libraries. Choose only the
ones that solve specific problems in your app.

2. Keep Libraries Updated:

Regularly check for updates to the libraries you are using. This ensures
bug fixes, security patches, and compatibility with the latest React
Native versions.

3. Be Mindful of Performance:

Libraries like React Native Reanimated and FlatList should be preferred


over less optimized solutions like Animated for performance-sensitive
areas (e.g., animations or long lists).

4. Test Libraries for Compatibility:

When integrating third-party libraries, ensure they are well-maintained


and compatible with your app's target platforms (iOS/Android).

5. Modularize Your Code:

Use libraries in a modular fashion to keep your codebase clean and


maintainable. Avoid directly using libraries in components if they don't
directly serve that component's purpose.

By using these libraries strategically, you can simplify development, add


powerful features, and optimize app performance.

Version 78

You might also like