Python Code Interview
Python Code Interview
# O(n) - Linear
def find_max(arr):
max_val = arr[0]
for num in arr: # visits each element once
if num > max_val:
max_val = num
return max_val
# O(n²) - Quadratic
def bubble_sort(arr):
for i in range(len(arr)):
for j in range(len(arr) - 1): # nested loop = O(n²)
if arr[j] > arr[j + 1]:
arr[j], arr[j + 1] = arr[j + 1], arr[j]
# Type checking
print(type(42)) # <class 'int'>
print(isinstance(42, int)) # True
🔄 Control Flow
Conditional Statements
# if-elif-else
score = 85
if score >= 90:
grade = 'A'
elif score >= 80:
grade = 'B'
else:
grade = 'C'
# Ternary operator
result = "Pass" if score >= 60 else "Fail"
# Multiple conditions
if score >= 80 and attendance >= 75:
print("Eligible for honors")
Loops
# For loops
for i in range(5): # 0, 1, 2, 3, 4
print(i)
# While loops
count = 0
while count < 5:
print(count)
count += 1
# Loop control
for i in range(10):
if i == 3:
continue # skip this iteration
if i == 7:
break # exit loop
print(i)
📋 Data Structures
Lists (Dynamic Arrays)
# Creation and basic operations - O(1) append, O(n) insert
arr = [1, 2, 3]
arr.append(4) # [1, 2, 3, 4] - O(1)
arr.insert(0, 0) # [0, 1, 2, 3, 4] - O(n)
arr.remove(2) # [0, 1, 3, 4] - O(n)
popped = arr.pop() # returns 4, arr = [0, 1, 3] - O(1)
# Dictionary methods
print(person.get("age", 0)) # 30 (with default)
print(person.keys()) # dict_keys(['name', 'age', 'city'])
print(person.values()) # dict_values(['Alice', 30, 'NYC'])
print(person.items()) # dict_items([('name', 'Alice'), ...])
# Dictionary comprehension
word_lengths = {word: len(word) for word in ["python", "java", "go"]}
Sets
# Unique elements, O(1) average for add/remove/lookup
unique_nums = {1, 2, 3, 3, 4} # {1, 2, 3, 4}
unique_nums.add(5)
unique_nums.remove(1)
# Set operations
set1 = {1, 2, 3}
set2 = {3, 4, 5}
print(set1 & set2) # {3} - intersection
print(set1 | set2) # {1, 2, 3, 4, 5} - union
print(set1 - set2) # {1, 2} - difference
Tuples
# Immutable sequences
coordinates = (10, 20)
x, y = coordinates # tuple unpacking
print(x) # 10
# Variable arguments
def sum_all(*args):
return sum(args)
def print_info(**kwargs):
for key, value in kwargs.items():
print(f"{key}: {value}")
# Higher-order functions
filtered = list(filter(lambda x: x % 2 == 0, numbers)) # [2, 4]
def introduce(self):
return f"Hi, I'm {self.name} and I'm {self.age} years old"
def __str__(self):
return f"Person(name={self.name}, age={self.age})"
def __repr__(self):
return f"Person('{self.name}', {self.age})"
# Inheritance
class Student(Person):
def __init__(self, name, age, student_id):
super().__init__(name, age) # Call parent constructor
self.student_id = student_id
def study(self):
return f"{self.name} is studying"
# Usage
alice = Person("Alice", 25)
bob = Student("Bob", 20, "S12345")
⚠️ Exception Handling
try:
result = 10 / 0
except ZeroDivisionError as e:
print(f"Error: {e}")
except Exception as e:
print(f"Unexpected error: {e}")
else:
print("No errors occurred")
finally:
print("This always runs")
# Custom exceptions
class CustomError(Exception):
def __init__(self, message):
self.message = message
super().__init__(self.message)
def validate_age(age):
if age < 0:
raise CustomError("Age cannot be negative")
return age
# Example usage
counter = Counter("hello") # Counter({'l': 2, 'h': 1, 'e': 1, 'o': 1})
dd = defaultdict(list) # default value is empty list
queue = deque([1, 2, 3]) # efficient append/pop from both ends
🧮 Essential Algorithms
Searching
# Binary Search - O(log n)
def binary_search(arr, target):
left, right = 0, len(arr) - 1
Sorting
# Quick Sort - O(n log n) average, O(n²) worst
def quicksort(arr):
if len(arr) <= 1:
return arr
pivot = arr[len(arr) // 2]
left = [x for x in arr if x < pivot]
middle = [x for x in arr if x == pivot]
right = [x for x in arr if x > pivot]
return []
return max_sum
return []
while stack:
node = stack.pop()
if node not in visited:
visited.add(node)
print(node)
stack.extend(graph[node])
🚀 Advanced Python Features
Decorators
def timer(func):
import time
def wrapper(*args, **kwargs):
start = time.time()
result = func(*args, **kwargs)
end = time.time()
print(f"{func.__name__} took {end - start:.4f} seconds")
return result
return wrapper
@timer
def slow_function():
time.sleep(1)
return "Done"
Generators
def fibonacci():
a, b = 0, 1
while True:
yield a
a, b = b, a + b
# Usage
fib = fibonacci()
for _ in range(10):
print(next(fib)) # 0, 1, 1, 2, 3, 5, 8, 13, 21, 34
Context Managers
# File handling with automatic cleanup
with open('file.txt', 'r') as f:
content = f.read()
# File automatically closed
with Timer():
time.sleep(1)
# Check if palindrome
def is_palindrome(s):
return s == s[::-1]
Memory Optimization
# Use generators for large datasets
def process_large_file(filename):
with open(filename, 'r') as f:
for line in f: # doesn't load entire file into memory
yield line.strip()
# Use slots for memory-efficient classes
class Point:
__slots__ = ['x', 'y'] # reduces memory overhead
While coding:
Space Complexities:
O(n) Linear for (let i = 0; i < n; Time grows linearly with input
i++)
// O(n) - Linear
function findMax(arr) {
let max = arr[0];
for (let i = 1; i < arr.length; i++) { // visits each element once
if (arr[i] > max) {
max = arr[i];
}
}
return max;
}
// O(n²) - Quadratic
function bubbleSort(arr) {
for (let i = 0; i < arr.length; i++) {
for (let j = 0; j < arr.length - 1; j++) { // nested loop = O(n²)
if (arr[j] > arr[j + 1]) {
[arr[j], arr[j + 1]] = [arr[j + 1], arr[j]];
}
}
}
return arr;
}
// Variable declarations
var oldWay = "function scoped"; // avoid in modern JS
let blockScoped = "block scoped"; // preferred
const constant = "cannot reassign"; // preferred for constants
// String operations
const str = "JavaScript";
console.log(str[0]); // 'J' - indexing
console.log(str.length); // 10 - length
console.log(str.slice(0, 4)); // 'Java' - slicing
console.log(str.split('')); // ['J','a','v','a','S','c','r','i','p','t']
console.log(str.toLowerCase()); // 'javascript'
🔄 Control Flow
Conditional Statements
// if-else if-else
const score = 85;
let grade;
if (score >= 90) {
grade = 'A';
} else if (score >= 80) {
grade = 'B';
} else {
grade = 'C';
}
// Ternary operator
const result = score >= 60 ? "Pass" : "Fail";
// Switch statement
switch (grade) {
case 'A':
console.log("Excellent!");
break;
case 'B':
console.log("Good job!");
break;
default:
console.log("Keep trying!");
}
// Logical operators
if (score >= 80 && attendance >= 75) {
console.log("Eligible for honors");
}
Loops
// For loops
for (let i = 0; i < 5; i++) { // 0, 1, 2, 3, 4
console.log(i);
}
// For...of (values)
const arr = [1, 2, 3, 4, 5];
for (const value of arr) {
console.log(value); // 1, 2, 3, 4, 5
}
// For...in (keys/indices)
for (const index in arr) {
console.log(index, arr[index]); // 0 1, 1 2, 2 3, 3 4, 4 5
}
// While loops
let count = 0;
while (count < 5) {
console.log(count);
count++;
}
// Loop control
for (let i = 0; i < 10; i++) {
if (i === 3) continue; // skip this iteration
if (i === 7) break; // exit loop
console.log(i);
}
📋 Data Structures
Arrays
// Creation and basic operations - O(1) push, O(n) unshift
const arr = [1, 2, 3];
arr.push(4); // [1, 2, 3, 4] - O(1) add to end
arr.unshift(0); // [0, 1, 2, 3, 4] - O(n) add to beginning
arr.pop(); // returns 4, arr = [0, 1, 2, 3] - O(1)
arr.shift(); // returns 0, arr = [1, 2, 3] - O(n)
// Important array methods for interviews
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(x => x * 2); // [2, 4, 6, 8, 10]
const evens = numbers.filter(x => x % 2 === 0); // [2, 4]
const sum = numbers.reduce((acc, x) => acc + x, 0); // 15
const found = numbers.find(x => x > 3); // 4
const index = numbers.findIndex(x => x > 3); // 3
// Array destructuring
const [first, second, ...rest] = [1, 2, 3, 4, 5];
console.log(first); // 1
console.log(rest); // [3, 4, 5]
// Access properties
console.log(person.name); // "Alice" - dot notation
console.log(person["age"]); // 30 - bracket notation
// Object methods
console.log(Object.keys(person)); // ["name", "age", "city"]
console.log(Object.values(person)); // ["Alice", 30, "NYC"]
console.log(Object.entries(person)); // [["name", "Alice"], ["age", 30], ["city", "NYC"]]
// Object destructuring
const {name, age} = person;
console.log(name); // "Alice"
Sets
// Unique elements, O(1) average for add/delete/has
const uniqueNums = new Set([1, 2, 3, 3, 4]); // Set {1, 2, 3, 4}
uniqueNums.add(5);
uniqueNums.delete(1);
console.log(uniqueNums.has(3)); // true
console.log(uniqueNums.size); // 4
// Convert to array
const arr = [...uniqueNums]; // [2, 3, 4, 5]
Maps
// Key-value pairs with any type of key
const map = new Map();
map.set("name", "Alice");
map.set(1, "number key");
map.set(true, "boolean key");
console.log(map.get("name")); // "Alice"
console.log(map.has(1)); // true
console.log(map.size); // 3
🔧 Functions
// Function declaration (hoisted)
function greet(name, greeting = "Hello") {
return `${greeting}, ${name}!`;
}
// Rest parameters
function sumAll(...numbers) {
return numbers.reduce((sum, num) => sum + num, 0);
}
// Higher-order functions
const numbers = [1, 2, 3, 4, 5];
const doubled = numbers.map(x => x * 2);
const evens = numbers.filter(x => x % 2 === 0);
const sum = numbers.reduce((acc, curr) => acc + curr, 0);
// Callback functions
function processArray(arr, callback) {
return arr.map(callback);
}
const squared = processArray([1, 2, 3], x => x * x);
// Method
introduce() {
return `Hi, I'm ${this.name} and I'm ${this.age} years old`;
}
// Static method
static species() {
return "Homo sapiens";
}
// Getter
get info() {
return `${this.name} (${this.age})`;
}
// Setter
set age(newAge) {
if (newAge >= 0) {
this._age = newAge;
}
}
}
// Inheritance
class Student extends Person {
constructor(name, age, studentId) {
super(name, age); // Call parent constructor
this.studentId = studentId;
}
study() {
return `${this.name} is studying`;
}
}
// Usage
const alice = new Person("Alice", 25);
const bob = new Student("Bob", 20, "S12345");
Animal.prototype.speak = function() {
return `${this.name} makes a sound`;
};
⚠️ Error Handling
// Try-catch-finally
try {
const result = riskyOperation();
console.log(result);
} catch (error) {
console.error("Error occurred:", error.message);
} finally {
console.log("This always runs");
}
🔄 Asynchronous JavaScript
Promises
// Creating a promise
const myPromise = new Promise((resolve, reject) => {
const success = true;
if (success) {
resolve("Operation successful");
} else {
reject(new Error("Operation failed"));
}
});
// Using promises
myPromise
.then(result => console.log(result))
.catch(error => console.error(error))
.finally(() => console.log("Done"));
Async/Await
// Async function
async function fetchData() {
try {
const response = await fetch('https://api.example.com/data');
const data = await response.json();
return data;
} catch (error) {
console.error("Failed to fetch data:", error);
throw error;
}
}
🧮 Essential Algorithms
Searching
// Binary Search - O(log n)
function binarySearch(arr, target) {
let left = 0;
let right = arr.length - 1;
Sorting
// Quick Sort - O(n log n) average, O(n²) worst
function quickSort(arr) {
if (arr.length <= 1) {
return arr;
}
// Built-in sorting
const numbers = [3, 1, 4, 1, 5, 9];
numbers.sort((a, b) => a - b); // ascending: [1, 1, 3, 4, 5, 9]
numbers.sort((a, b) => b - a); // descending: [9, 5, 4, 3, 1, 1]
return [];
}
return maxSum;
}
Hash Map for Lookups
function twoSum(nums, target) {
const seen = new Map();
if (seen.has(complement)) {
return [seen.get(complement), i];
}
seen.set(nums[i], i);
}
return [];
}
if (!visited.has(node)) {
visited.add(node);
console.log(node);
return function() {
count++;
return count;
};
}
return {
add: function(x) { result += x; return this; },
multiply: function(x) { result *= x; return this; },
getResult: function() { return result; }
};
})();
calculator.add(5).multiply(2).getResult(); // 10
Animal.prototype.speak = function() {
return `${this.name} makes a sound`;
};
// Set up inheritance
Dog.prototype = Object.create(Animal.prototype);
Dog.prototype.constructor = Dog;
Dog.prototype.bark = function() {
return `${this.name} barks loudly!`;
};
// Object destructuring
const {name, age, city = "Unknown"} = person;
// Spread operator
const arr1 = [1, 2, 3];
const arr2 = [4, 5, 6];
const combined = [...arr1, ...arr2]; // [1, 2, 3, 4, 5, 6]
// Function parameters
function sum(...numbers) {
return numbers.reduce((total, num) => total + num, 0);
}
Template Literals
const name = "Alice";
const age = 30;
// Multi-line strings
const multiLine = `
This is a
multi-line
string
`;
⚡ ES6+ Features
Let, Const, and Block Scope
// var vs let vs const
if (true) {
var varVariable = "function scoped";
let letVariable = "block scoped";
const constVariable = "block scoped and immutable";
}
Default Parameters
function greet(name = "World", greeting = "Hello") {
return `${greeting}, ${name}!`;
}
Modules (Import/Export)
// math.js - Export
export const PI = 3.14159;
export function add(a, b) {
return a + b;
}
export default function multiply(a, b) {
return a * b;
}
// main.js - Import
import multiply, { PI, add } from './math.js';
import * as Math from './math.js';
console.log(add(2, 3)); // 5
console.log(multiply(4, 5)); // 20
console.log(PI); // 3.14159
// Check if palindrome
function isPalindrome(str) {
const cleaned = str.toLowerCase().replace(/[^a-z0-9]/g, '');
return cleaned === cleaned.split('').reverse().join('');
}
// Remove duplicates from array
function removeDuplicates(arr) {
return [...new Set(arr)];
}
// or using filter
function removeDuplicatesFilter(arr) {
return arr.filter((item, index) => arr.indexOf(item) === index);
}
// Event handling
element.addEventListener('click', function(event) {
event.preventDefault();
console.log('Element clicked!');
});
Performance Tips
// Use const and let instead of var
const config = { apiUrl: 'https://api.example.com' };
let counter = 0;
// Throttling
function throttle(func, delay) {
let lastCall = 0;
return function(...args) {
const now = Date.now();
if (now - lastCall >= delay) {
lastCall = now;
func.apply(this, args);
}
};
}
JavaScript-specific gotchas:
Space Complexities:
⚡✨
memorize syntax. Focus on problem-solving patterns and clean code. Good luck with your
JavaScript interviews!
BIG O NOTATION
Big O notation is a way to describe how fast an algorithm's runtime or memory usage grows as
the input size increases. It focuses on the **worst-case scenario** and ignores constant factors,
giving you a high-level understanding of efficiency.
### **Example:**
- If an algorithm is **O(n)**, doubling the input size roughly doubles the time.
- If it's **O(n²)**, doubling the input could quadruple the time.
---
---
---
## 🚀 React Basics
### What is React?
- JavaScript library for building user interfaces (especially SPAs)
- Created by Facebook, focuses on component-based architecture
- Uses Virtual DOM for efficient updates
```javascript
// Simple React Component
function Welcome() {
return <h1>Hello, World!</h1>;
}
```
```javascript
// JSX Example
const element = <h1>Hello {name}!</h1>;
// Compiles to:
const element = React.createElement('h1', null, 'Hello ', name, '!');
// Fragment usage
return (
<>
<h1>Title</h1>
<p>Content</p>
</>
);
```
### Components
- Building blocks of React apps
- Two types: Functional (modern) and Class-based (legacy)
- Accept props and return JSX
```javascript
// Functional Component (Preferred)
function Button({ text, onClick, disabled = false }) {
return (
<button onClick={onClick} disabled={disabled}>
{text}
</button>
);
}
// Usage
<Button text="Click me" onClick={() => alert('Clicked!')} />
```
---
## ⚡ Hooks
### useState
- Adds state to functional components
- Returns [currentState, setterFunction]
- State updates are asynchronous
```javascript
function Counter() {
const [count, setCount] = useState(0);
return (
<div>
<p>Count: {count}</p>
<button onClick={increment}>+</button>
</div>
);
}
```
### useEffect
- Handles side effects (API calls, subscriptions, DOM manipulation)
- Runs after render by default
- Control with dependency array
```javascript
function UserProfile({ userId }) {
const [user, setUser] = useState(null);
const [loading, setLoading] = useState(true);
useEffect(() => {
// Effect function
setLoading(true);
fetchUser(userId)
.then(userData => {
setUser(userData);
setLoading(false);
});
### useContext
- Consume context values without prop drilling
- Cleaner alternative to Consumer pattern
```javascript
const ThemeContext = createContext();
function App() {
const [theme, setTheme] = useState('dark');
return (
<ThemeContext.Provider value={{ theme, setTheme }}>
<Header />
<Main />
</ThemeContext.Provider>
);
}
function Header() {
const { theme, setTheme } = useContext(ThemeContext);
return (
<header className={theme}>
<button onClick={() => setTheme(theme === 'dark' ? 'light' : 'dark')}>
Toggle Theme
</button>
</header>
);
}
```
```javascript
// Custom hook for counter logic
function useCounter(initialValue = 0) {
const [count, setCount] = useState(initialValue);
useEffect(() => {
const fetchData = async () => {
try {
setLoading(true);
const response = await fetch(url);
const result = await response.json();
setData(result);
} catch (err) {
setError(err);
} finally {
setLoading(false);
}
};
fetchData();
}, [url]);
// Usage
function Counter() {
const { count, increment, decrement, reset } = useCounter(10);
return (
<div>
<span>{count}</span>
<button onClick={increment}>+</button>
<button onClick={decrement}>-</button>
<button onClick={reset}>Reset</button>
</div>
);
}
```
---
## 🗃️ State Management
### Props vs State
- **Props**: Read-only data passed from parent to child
- **State**: Mutable data owned by the component
```javascript
// Props (read-only, passed down)
function Welcome({ name, age }) {
// Cannot modify name or age here
return <h1>Hello {name}, you are {age} years old</h1>;
}
```javascript
function App() {
const [temperature, setTemperature] = useState(0);
return (
<div>
<TemperatureInput
temperature={temperature}
onTemperatureChange={setTemperature}
/>
<BoilingVerdict celsius={temperature} />
</div>
);
}
### useReducer
- Alternative to useState for complex state logic
- Similar to Redux pattern
- Good for state with multiple sub-values or complex transitions
```javascript
const initialState = { todos: [], filter: 'all' };
function TodoApp() {
const [state, dispatch] = useReducer(todoReducer, initialState);
return (
<div>
<input onKeyPress={(e) => {
if (e.key === 'Enter') {
addTodo(e.target.value);
e.target.value = '';
}
}} />
{state.todos.map(todo => (
<div key={todo.id} onClick={() => toggleTodo(todo.id)}>
{todo.text} {todo.completed ? '✓' : '○'}
</div>
))}
</div>
);
}
```
---
## ⚡ Performance Optimization
### React.memo
- Higher-order component that memoizes result
- Prevents re-renders if props haven't changed
- Shallow comparison by default
```javascript
// Without memo - re-renders every time parent renders
function ExpensiveComponent({ name, data }) {
console.log('Rendering ExpensiveComponent');
return <div>Hello {name}</div>;
}
// With memo - only re-renders if props change
const OptimizedComponent = React.memo(function ExpensiveComponent({ name, data }) {
console.log('Rendering ExpensiveComponent');
return <div>Hello {name}</div>;
});
### useMemo
- Memoizes expensive calculations
- Only recalculates when dependencies change
- Don't overuse - has its own overhead
```javascript
function ExpensiveList({ items, filter, sortBy }) {
// Expensive calculation memoized
const filteredAndSortedItems = useMemo(() => {
console.log('Filtering and sorting...');
return items
.filter(item => item.name.includes(filter))
.sort((a, b) => a[sortBy] - b[sortBy]);
}, [items, filter, sortBy]); // Only recalculate when these change
return (
<ul>
{filteredAndSortedItems.map(item => (
<li key={item.id}>{item.name}</li>
))}
</ul>
);
}
```
### useCallback
- Memoizes functions to prevent child re-renders
- Useful when passing callbacks to optimized child components
```javascript
function Parent({ items }) {
const [count, setCount] = useState(0);
return (
<div>
<button onClick={() => setCount(count + 1)}>Count: {count}</button>
{items.map(item => (
<ExpensiveChild
key={item.id}
item={item}
onClick={handleClick}
onDelete={handleDelete}
/>
))}
</div>
);
}
---
```javascript
function MyComponent({ userId, theme }) {
// Run once on mount (componentDidMount equivalent)
useEffect(() => {
console.log('Component mounted');
// Good for: initial API calls, event listeners setup
}, []);
useEffect(() => {
applyTheme(theme);
}, [theme]); // Only run when theme changes
// Multiple dependencies
useEffect(() => {
updateUserTheme(userId, theme);
}, [userId, theme]); // Run when either changes
}
```
// Set up timer
const timer = setInterval(() => {
console.log('Timer tick');
}, 1000);
fetch(`/api/users/${userId}`, {
signal: controller.signal
}).then(response => {
// Handle response
});
return () => {
controller.abort(); // Cancel request if userId changes
};
}, [userId]);
}
```
---
## 🎨 Common Patterns
### Conditional Rendering
- Show different UI based on conditions
- Multiple techniques available
```javascript
function UserGreeting({ user, isLoading, error }) {
// Early return pattern
if (isLoading) return <div>Loading...</div>;
if (error) return <div>Error: {error.message}</div>;
if (!user) return <div>Please log in</div>;
function App() {
const [user, setUser] = useState(null);
const [showModal, setShowModal] = useState(false);
return (
<div>
{/* Logical AND - show if condition is true */}
{user && <h1>Welcome back, {user.name}!</h1>}
{!user && <LoginButton />}
```javascript
function TodoList({ todos, onToggle, onDelete }) {
return (
<ul>
{todos.map(todo => (
<li key={todo.id}> {/* Always use unique, stable keys */}
<span
style={{
textDecoration: todo.completed ? 'line-through' : 'none'
}}
onClick={() => onToggle(todo.id)}
>
{todo.text}
</span>
<button onClick={() => onDelete(todo.id)}>Delete</button>
</li>
))}
</ul>
);
}
✅
// Key guidelines:
❌
// Use unique, stable IDs
❌
// Don't use array index if list can change order
// Don't use random values
// Good keys
todos.map(todo => <Todo key={todo.id} todo={todo} />)
```javascript
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false, error: null };
}
static getDerivedStateFromError(error) {
// Update state to show error UI
return { hasError: true, error };
}
componentDidCatch(error, errorInfo) {
// Log error to reporting service
console.error('Error caught by boundary:', error, errorInfo);
// You can also log to an error reporting service here
}
render() {
if (this.state.hasError) {
// Fallback UI
return (
<div>
<h2>Something went wrong.</h2>
<details style={{ whiteSpace: 'pre-wrap' }}>
{this.state.error && this.state.error.toString()}
</details>
</div>
);
}
return this.props.children;
}
}
// Usage
function App() {
return (
<ErrorBoundary>
<Header />
<ErrorBoundary> {/* Can nest for granular error handling */}
<MainContent />
</ErrorBoundary>
<Footer />
</ErrorBoundary>
);
}
```
---
## 🚀 Advanced Concepts
### Higher-Order Components (HOC)
- Function that takes a component and returns enhanced component
- Used for cross-cutting concerns (auth, logging, etc.)
```javascript
// HOC for authentication
function withAuth(WrappedComponent) {
return function AuthComponent(props) {
const { user, loading } = useContext(AuthContext);
// Usage
const ProtectedProfile = withAuth(ProfileComponent);
const ProfileWithLoading = withLoading(withAuth(ProfileComponent));
```javascript
// Render prop component
function DataFetcher({ url, children }) {
const [data, setData] = useState(null);
const [loading, setLoading] = useState(true);
const [error, setError] = useState(null);
useEffect(() => {
fetch(url)
.then(res => res.json())
.then(data => {
setData(data);
setLoading(false);
})
.catch(err => {
setError(err);
setLoading(false);
});
}, [url]);
useEffect(() => {
const handleMouseMove = (e) => {
setMouse({ x: e.clientX, y: e.clientY });
};
document.addEventListener('mousemove', handleMouseMove);
return () => document.removeEventListener('mousemove', handleMouseMove);
}, []);
return children(mouse);
}
// Usage
<MouseTracker>
{mouse => (
<div>Mouse position: {mouse.x}, {mouse.y}</div>
)}
</MouseTracker>
```
### Portals
- Render children into DOM node outside parent hierarchy
- Useful for modals, tooltips, dropdowns
```javascript
import { createPortal } from 'react-dom';
return createPortal(
<div className="modal-overlay" onClick={onClose}>
<div className="modal-content" onClick={e => e.stopPropagation()}>
<button className="modal-close" onClick={onClose}>×</button>
{children}
</div>
</div>,
document.getElementById('modal-root') // Must exist in HTML
);
}
```javascript
// Create context with default value
const AppContext = createContext({
user: null,
theme: 'light',
setUser: () => {},
setTheme: () => {}
});
// Provider component
function AppProvider({ children }) {
const [user, setUser] = useState(null);
const [theme, setTheme] = useState('light');
const value = {
user,
theme,
setUser,
setTheme,
login: async (credentials) => {
const user = await api.login(credentials);
setUser(user);
},
logout: () => {
setUser(null);
api.logout();
}
};
return (
<AppContext.Provider value={value}>
{children}
</AppContext.Provider>
);
}
// Usage in components
function Header() {
const { user, theme, logout, setTheme } = useApp();
return (
<header className={`header ${theme}`}>
{user ? (
<div>
Welcome, {user.name}
<button onClick={logout}>Logout</button>
</div>
):(
<LoginButton />
)}
<button onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}>
Toggle Theme
</button>
</header>
);
}
```
---
return (
<form onSubmit={handleSubmit}>
<input
name="name"
value={formData.name}
onChange={handleChange}
placeholder="Name"
/>
<input
name="email"
value={formData.email}
onChange={handleChange}
placeholder="Email"
/>
<textarea
name="message"
value={formData.message}
onChange={handleChange}
placeholder="Message"
/>
<button type="submit">Send</button>
</form>
);
}
```
fireEvent.click(button);
expect(screen.getByText('1')).toBeInTheDocument();
});
```
---
---
*Remember: React is about thinking in components and data flow. Focus on understanding the
why behind each concept, not just memorizing syntax. Good luck with your interviews!*