dicembre 21, 2025
18 min di lettura

Domande per Colloqui di Lavoro per Sviluppatori Senior React Native: Guida Completa

interview
career-advice
job-search
Domande per Colloqui di Lavoro per Sviluppatori Senior React Native: Guida Completa
Milad Bonakdar

Milad Bonakdar

Autore

Padroneggia lo sviluppo avanzato in React Native con domande essenziali per il colloquio che riguardano l'ottimizzazione delle prestazioni, i moduli nativi, la gestione dello stato, il testing, i modelli di architettura e le migliori pratiche cross-platform per sviluppatori senior.


Introduzione

Ci si aspetta che gli sviluppatori senior di React Native progettino applicazioni multipiattaforma scalabili, ottimizzino le prestazioni, integrino moduli nativi e prendano decisioni architetturali consapevoli. Questo ruolo richiede una profonda esperienza in React Native, gestione dello stato, sviluppo nativo e la capacità di risolvere sfide complesse nello sviluppo mobile.

Questa guida completa copre le domande essenziali per i colloqui per Sviluppatori Senior React Native, spaziando tra concetti avanzati di React, ottimizzazione delle prestazioni, gestione dello stato, moduli nativi, testing e modelli architetturali. Ogni domanda include risposte dettagliate, valutazione della rarità e valutazioni della difficoltà.


React & Hooks Avanzati (5 Domande)

1. Spiega useMemo e useCallback. Quando dovresti usarli?

Risposta: Entrambi gli hook ottimizzano le prestazioni memorizzando valori/funzioni.

  • useMemo: Memorizza valori computati (calcoli costosi)
  • useCallback: Memorizza riferimenti a funzioni (previene la ricreazione)
  • Quando usarli: Solo quando hai problemi di prestazioni. L'ottimizzazione prematura può rendere il codice più difficile da leggere.
import { useMemo, useCallback, useState } from 'react';

function ExpensiveComponent({ items, onItemClick }) {
  // useMemo - memorizza calcoli costosi
  const sortedItems = useMemo(() => {
    console.log('Ordinamento elementi...');
    return items.sort((a, b) => a.price - b.price);
  }, [items]); // Ricalcola solo quando gli elementi cambiano
  
  // useCallback - memorizza la funzione
  const handleClick = useCallback((id) => {
    console.log('Elemento cliccato:', id);
    onItemClick(id);
  }, [onItemClick]); // Ricrea solo quando onItemClick cambia
  
  return (
    <FlatList
      data={sortedItems}
      renderItem={({ item }) => (
        <ItemRow item={item} onClick={handleClick} />
      )}
    />
  );
}

// Componente figlio con React.memo
const ItemRow = React.memo(({ item, onClick }) => {
  console.log('Rendering elemento:', item.id);
  return (
    <TouchableOpacity onPress={() => onClick(item.id)}>
      <Text>{item.name}</Text>
    </TouchableOpacity>
  );
});

Rarità: Molto Comune Difficoltà: Media


2. Cos'è useRef e quali sono i suoi casi d'uso?

Risposta: useRef crea un riferimento mutabile che persiste tra i rendering senza causare re-rendering.

  • Casi d'uso:
    • Accesso a elementi DOM/nativi
    • Memorizzazione di valori mutabili senza attivare il re-rendering
    • Conservazione dei valori precedenti
    • Memorizzazione di timer/intervalli
import { useRef, useEffect } from 'react';
import { TextInput, Animated } from 'react-native';

function FormComponent() {
  const inputRef = useRef(null);
  const previousValue = useRef('');
  const animatedValue = useRef(new Animated.Value(0)).current;
  
  useEffect(() => {
    // Focus sull'input al mount
    inputRef.current?.focus();
  }, []);
  
  const handleChange = (text) => {
    console.log('Precedente:', previousValue.current);
    console.log('Corrente:', text);
    previousValue.current = text;
  };
  
  const startAnimation = () => {
    Animated.timing(animatedValue, {
      toValue: 1,
      duration: 300,
      useNativeDriver: true,
    }).start();
  };
  
  return (
    <View>
      <TextInput ref={inputRef} onChangeText={handleChange} />
      <Animated.View style={{ opacity: animatedValue }}>
        <Text>Contenuto animato</Text>
      </Animated.View>
    </View>
  );
}

// Esempio di timer
function Timer() {
  const intervalRef = useRef(null);
  const [count, setCount] = useState(0);
  
  useEffect(() => {
    intervalRef.current = setInterval(() => {
      setCount(c => c + 1);
    }, 1000);
    
    return () => clearInterval(intervalRef.current);
  }, []);
  
  return <Text>{count}</Text>;
}

Rarità: Comune Difficoltà: Media


3. Spiega gli Hook Personalizzati e quando crearli.

Risposta: Gli hook personalizzati estraggono la logica stateful riutilizzabile in funzioni separate.

  • Vantaggi: Riutilizzo del codice, separazione delle preoccupazioni, testing più semplice
  • Convenzione: Deve iniziare con "use"
// Hook personalizzato per il fetching API
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    const fetchData = async () => {
      try {
        const response = await fetch(url);
        const json = await response.json();
        setData(json);
      } catch (err) {
        setError(err.message);
      } finally {
        setLoading(false);
      }
    };
    
    fetchData();
  }, [url]);
  
  return { data, loading, error };
}

// Hook personalizzato per la gestione dei form
function useForm(initialValues) {
  const [values, setValues] = useState(initialValues);
  const [errors, setErrors] = useState({});
  
  const handleChange = (name, value) => {
    setValues(prev => ({ ...prev, [name]: value }));
  };
  
  const validate = (validationRules) => {
    const newErrors = {};
    Object.keys(validationRules).forEach(field => {
      const rule = validationRules[field];
      if (rule.required && !values[field]) {
        newErrors[field] = `${field} è richiesto`;
      }
    });
    setErrors(newErrors);
    return Object.keys(newErrors).length === 0;
  };
  
  return { values, errors, handleChange, validate };
}

// Utilizzo
function UserProfile() {
  const { data, loading, error } = useFetch('https://api.example.com/user');
  const { values, errors, handleChange, validate } = useForm({
    name: '',
    email: '',
  });
  
  if (loading) return <ActivityIndicator />;
  if (error) return <Text>Errore: {error}</Text>;
  
  return <Text>{data.name}</Text>;
}

Rarità: Comune Difficoltà: Media


4. Cos'è React Context e quando dovresti usarlo?

Risposta: Context fornisce un modo per passare dati attraverso l'albero dei componenti senza prop drilling.

  • Casi d'uso: Tema, autenticazione, preferenze di lingua
  • Attenzione: Può causare re-rendering non necessari se non usato con attenzione
import { createContext, useContext, useState } from 'react';

// Crea context
const ThemeContext = createContext();
const AuthContext = createContext();

// Theme Provider
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
  
  const toggleTheme = () => {
    setTheme(prev => prev === 'light' ? 'dark' : 'light');
  };
  
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// Auth Provider
function AuthProvider({ children }) {
  const [user, setUser] = useState(null);
  
  const login = async (credentials) => {
    const user = await loginAPI(credentials);
    setUser(user);
  };
  
  const logout = () => {
    setUser(null);
  };
  
  return (
    <AuthContext.Provider value={{ user, login, logout }}>
      {children}
    </AuthContext.Provider>
  );
}

// Hook personalizzati per context
function useTheme() {
  const context = useContext(ThemeContext);
  if (!context) {
    throw new Error('useTheme deve essere usato all'interno di ThemeProvider');
  }
  return context;
}

function useAuth() {
  return useContext(AuthContext);
}

// Utilizzo
function App() {
  return (
    <ThemeProvider>
      <AuthProvider>
        <MainApp />
      </AuthProvider>
    </ThemeProvider>
  );
}

function ThemedButton() {
  const { theme, toggleTheme } = useTheme();
  const { user } = useAuth();
  
  return (
    <TouchableOpacity
      style={{ backgroundColor: theme === 'light' ? '#fff' : '#333' }}
      onPress={toggleTheme}
    >
      <Text>{user ? `Ciao, ${user.name}` : 'Ospite'}</Text>
    </TouchableOpacity>
  );
}

Rarità: Molto Comune Difficoltà: Media


5. Spiega la differenza tra useEffect e useLayoutEffect.

Risposta: Entrambi eseguono side effect, ma in momenti diversi:

  • useEffect: Viene eseguito asincronamente dopo che il rendering è stato disegnato sullo schermo
  • useLayoutEffect: Viene eseguito sincronicamente prima del paint (blocca gli aggiornamenti visivi)
  • Usa useLayoutEffect quando: Devi misurare il DOM o prevenire sfarfallii visivi
import { useEffect, useLayoutEffect, useRef, useState } from 'react';

function MeasureComponent() {
  const [height, setHeight] = useState(0);
  const elementRef = useRef(null);
  
  // useLayoutEffect - misura prima del paint
  useLayoutEffect(() => {
    if (elementRef.current) {
      const { height } = elementRef.current.measure((x, y, width, height) => {
        setHeight(height);
      });
    }
  }, []);
  
  // useEffect - dopo il paint
  useEffect(() => {
    console.log('Componente renderizzato');
  }, []);
  
  return (
    <View ref={elementRef}>
      <Text>Altezza: {height}</Text>
    </View>
  );
}

Rarità: Media Difficoltà: Alta


Gestione dello Stato (4 Domande)

6. Spiega Redux e i suoi principi fondamentali.

Risposta: Redux è un contenitore di stato prevedibile per app JavaScript.

Loading diagram...
  • Principi fondamentali:
    • Unica fonte di verità (un solo store)
    • Lo stato è di sola lettura (invia azioni per cambiare)
    • Modifiche apportate con funzioni pure (reducer)
// Tipi di azione
const ADD_TODO = 'ADD_TODO';
const TOGGLE_TODO = 'TOGGLE_TODO';

// Creatori di azioni
const addTodo = (text) => ({
  type: ADD_TODO,
  payload: { id: Date.now(), text, completed: false },
});

const toggleTodo = (id) => ({
  type: TOGGLE_TODO,
  payload: id,
});

// Reducer
const todosReducer = (state = [], action) => {
  switch (action.type) {
    case ADD_TODO:
      return [...state, action.payload];
    case TOGGLE_TODO:
      return state.map(todo =>
        todo.id === action.payload
          ? { ...todo, completed: !todo.completed }
          : todo
      );
    default:
      return state;
  }
};

// Store
import { createStore } from 'redux';
const store = createStore(todosReducer);

// Componente React Native
import { useSelector, useDispatch } from 'react-redux';

function TodoList() {
  const todos = useSelector(state => state.todos);
  const dispatch = useDispatch();
  
  return (
    <View>
      <FlatList
        data={todos}
        renderItem={({ item }) => (
          <TouchableOpacity onPress={() => dispatch(toggleTodo(item.id))}>
            <Text style={{ textDecorationLine: item.completed ? 'line-through' : 'none' }}>
              {item.text}
            </Text>
          </TouchableOpacity>
        )}
      />
      <Button title="Aggiungi" onPress={() => dispatch(addTodo('Nuovo Task'))} />
    </View>
  );
}

Rarità: Molto Comune Difficoltà: Alta


7. Cos'è Redux Toolkit e come semplifica Redux?

Risposta: Redux Toolkit è il modo ufficiale raccomandato per scrivere la logica Redux.

  • Vantaggi:
    • Meno boilerplate
    • Immer integrato per aggiornamenti immutabili
    • Include Redux Thunk
    • Migliore supporto TypeScript
import { createSlice, configureStore } from '@reduxjs/toolkit';

// Slice (combina azioni e reducer)
const todosSlice = createSlice({
  name: 'todos',
  initialState: [],
  reducers: {
    addTodo: (state, action) => {
      // Immer permette codice "mutante"
      state.push({
        id: Date.now(),
        text: action.payload,
        completed: false,
      });
    },
    toggleTodo: (state, action) => {
      const todo = state.find(t => t.id === action.payload);
      if (todo) {
        todo.completed = !todo.completed;
      }
    },
  },
});

export const { addTodo, toggleTodo } = todosSlice.actions;

// Store
const store = configureStore({
  reducer: {
    todos: todosSlice.reducer,
  },
});

// Async thunk
import { createAsyncThunk } from '@reduxjs/toolkit';

export const fetchTodos = createAsyncThunk(
  'todos/fetchTodos',
  async () => {
    const response = await fetch('https://api.example.com/todos');
    return response.json();
  }
);

const todosSlice = createSlice({
  name: 'todos',
  initialState: { items: [], loading: false, error: null },
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(fetchTodos.pending, (state) => {
        state.loading = true;
      })
      .addCase(fetchTodos.fulfilled, (state, action) => {
        state.loading = false;
        state.items = action.payload;
      })
      .addCase(fetchTodos.rejected, (state, action) => {
        state.loading = false;
        state.error = action.error.message;
      });
  },
});

Rarità: Comune Difficoltà: Media


8. Quali sono le alternative a Redux per la gestione dello stato?

Risposta: Esistono diverse soluzioni per la gestione dello stato:

  • Context API + useReducer: Integrato, buono per app semplici
  • MobX: Basato su osservabili, meno boilerplate
  • Zustand: Minimo, basato su hook
  • Recoil: Basato su atomi, di Facebook
  • Jotai: Atomi primitivi
// Esempio Zustand
import create from 'zustand';

const useStore = create((set) => ({
  todos: [],
  addTodo: (text) => set((state) => ({
    todos: [...state.todos, { id: Date.now(), text, completed: false }],
  })),
  toggleTodo: (id) => set((state) => ({
    todos: state.todos.map(todo =>
      todo.id === id ? { ...todo, completed: !todo.completed } : todo
    ),
  })),
}));

// Utilizzo
function TodoList() {
  const { todos, addTodo, toggleTodo } = useStore();
  
  return (
    <View>
      <FlatList
        data={todos}
        renderItem={({ item }) => (
          <TouchableOpacity onPress={() => toggleTodo(item.id)}>
            <Text>{item.text}</Text>
          </TouchableOpacity>
        )}
      />
    </View>
  );
}

Rarità: Comune Difficoltà: Media


9. Come gestisci gli effetti collaterali in Redux?

Risposta: Usa middleware per operazioni asincrone:

  • Redux Thunk: Funzioni che restituiscono funzioni
  • Redux Saga: Basato su generatori, più potente
  • Redux Observable: Basato su RxJS
// Redux Thunk
const fetchUser = (userId) => async (dispatch) => {
  dispatch({ type: 'FETCH_USER_REQUEST' });
  
  try {
    const response = await fetch(`https://api.example.com/users/${userId}`);
    const user = await response.json();
    dispatch({ type: 'FETCH_USER_SUCCESS', payload: user });
  } catch (error) {
    dispatch({ type: 'FETCH_USER_FAILURE', payload: error.message });
  }
};

// Utilizzo
dispatch(fetchUser(123));

// Redux Saga
import { call, put, takeEvery } from 'redux-saga/effects';

function* fetchUserSaga(action) {
  try {
    const user = yield call(fetch, `https://api.example.com/users/${action.payload}`);
    const data = yield call([user, 'json']);
    yield put({ type: 'FETCH_USER_SUCCESS', payload: data });
  } catch (error) {
    yield put({ type: 'FETCH_USER_FAILURE', payload: error.message });
  }
}

function* watchFetchUser() {
  yield takeEvery('FETCH_USER_REQUEST', fetchUserSaga);
}

Rarità: Comune Difficoltà: Alta


Ottimizzazione delle Prestazioni (5 Domande)

10. Come ottimizzi le prestazioni di FlatList?

Risposta: Molteplici strategie migliorano lo scrolling di FlatList:

  1. Usa keyExtractor: Fornisci chiavi univoche
  2. getItemLayout: Salta la misurazione per elementi ad altezza fissa
  3. removeClippedSubviews: Smonta le viste fuori dallo schermo (Android)
  4. maxToRenderPerBatch: Controlla la dimensione del batch
  5. windowSize: Controlla la finestra renderizzata
  6. initialNumToRender: Elementi da renderizzare inizialmente
  7. Memorizza renderItem: Previene re-rendering non necessari
import React, { memo, useCallback } from 'react';

const ITEM_HEIGHT = 80;

// Componente elemento memorizzato
const ListItem = memo(({ item, onPress }) => {
  return (
    <TouchableOpacity onPress={() => onPress(item.id)} style={{ height: ITEM_HEIGHT }}>
      <Text>{item.name}</Text>
    </TouchableOpacity>
  );
});

function OptimizedList({ data }) {
  const handlePress = useCallback((id) => {
    console.log('Premuto:', id);
  }, []);
  
  const renderItem = useCallback(({ item }) => (
    <ListItem item={item} onPress={handlePress} />
  ), [handlePress]);
  
  const keyExtractor = useCallback((item) => item.id.toString(), []);
  
  const getItemLayout = useCallback((data, index) => ({
    length: ITEM_HEIGHT,
    offset: ITEM_HEIGHT * index,
    index,
  }), []);
  
  return (
    <FlatList
      data={data}
      renderItem={renderItem}
      keyExtractor={keyExtractor}
      getItemLayout={getItemLayout}
      removeClippedSubviews={true}
      maxToRenderPerBatch={10}
      updateCellsBatchingPeriod={50}
      initialNumToRender={10}
      windowSize={5}
    />
  );
}

Rarità: Molto Comune Difficoltà: Media


11. Cos'è il bridge di React Native e come influisce sulle prestazioni?

Risposta: Il bridge è il livello di comunicazione tra JavaScript e il codice nativo.

  • Come funziona:
    • JavaScript viene eseguito in un thread separato
    • I moduli nativi vengono eseguiti in thread nativi
    • Il bridge serializza i dati tra loro (JSON)
  • Impatto sulle prestazioni:
    • La comunicazione del bridge è asincrona
    • Overhead di serializzazione
    • Può diventare un collo di bottiglia con comunicazioni frequenti
  • Soluzioni:
    • Minimizzare gli attraversamenti del bridge
    • Operazioni batch
    • Usa animazioni native (bypass del bridge)
    • Nuova Architettura (JSI) rimuove il bridge
// Male - frequenti attraversamenti del bridge
const BadAnimation = () => {
  const [position, setPosition] = useState(0);
  
  useEffect(() => {
    const interval = setInterval(() => {
      setPosition(p => p + 1); // Attraversamento del bridge ad ogni frame!
    }, 16);
    return () => clearInterval(interval);
  }, []);
  
  return <View style={{ transform: [{ translateX: position }] }} />;
};

// Bene - animazione nativa (nessun bridge)
const GoodAnimation = () => {
  const translateX = useRef(new Animated.Value(0)).current;
  
  useEffect(() => {
    Animated.timing(translateX, {
      toValue: 100,
      duration: 1000,
      useNativeDriver: true, // Esegue sul thread nativo!
    }).start();
  }, []);
  
  return <Animated.View style={{ transform: [{ translateX }] }} />;
};

Rarità: Comune Difficoltà: Alta


12. Come previeni re-rendering non necessari?

Risposta: Molteplici tecniche prevengono rendering sprecati:

  1. React.memo: Memorizza i componenti
  2. useMemo/useCallback: Memorizza valori/funzioni
  3. Prop key appropriate: Aiuta React a identificare i cambiamenti
  4. Evita oggetti/array inline: Crea nuovi riferimenti
  5. Dividi i componenti: Componenti più piccoli e focalizzati
// Male - crea un nuovo oggetto ad ogni rendering
function BadComponent() {
  return <ChildComponent style={{ margin: 10 }} />; // Nuovo oggetto!
}

// Bene - riferimento stabile
const styles = StyleSheet.create({
  container: { margin: 10 },
});

function GoodComponent() {
  return <ChildComponent style={styles.container} />;
}

// React.memo con confronto personalizzato
const ExpensiveComponent = React.memo(
  ({ data, onPress }) => {
    console.log('Rendering ExpensiveComponent');
    return (
      <View>
        <Text>{data.name}</Text>
        <Button onPress={onPress} />
      </View>
    );
  },
  (prevProps, nextProps) => {
    // Confronto personalizzato - riesegui il rendering solo se data.id è cambiato
    return prevProps.data.id === nextProps.data.id;
  }
);

// Dividi i componenti per isolare i re-rendering
function ParentComponent() {
  const [count, setCount] = useState(0);
  const [text, setText] = useState('');
  
  return (
    <View>
      {/* Riesegue il rendering solo quando count cambia */}
      <CountDisplay count={count} />
      
      {/* Riesegue il rendering solo quando text cambia */}
      <TextDisplay text={text} />
      
      <Button onPress={() => setCount(c => c + 1)} />
    </View>
  );
}

const CountDisplay = React.memo(({ count }) => <Text>{count}</Text>);
const TextDisplay = React.memo(({ text }) => <Text>{text}</Text>);

Rarità: Molto Comune Difficoltà: Media


13. Come ottimizzi le immagini in React Native?

Risposta: L'ottimizzazione delle immagini è fondamentale per le prestazioni:

  1. Ridimensiona le immagini: Usa dimensioni appropriate
  2. Memorizza le immagini nella cache: Usa librerie come react-native-fast-image
  3. Lazy loading: Carica le immagini su richiesta
  4. Caricamento progressivo: Mostra prima un segnaposto
  5. Usa il formato WebP: Migliore compressione
import FastImage from 'react-native-fast-image';

function OptimizedImage({ uri }) {
  return (
    <FastImage
      source={{
        uri,
        priority: FastImage.priority.normal,
        cache: FastImage.cacheControl.immutable,
      }}
      resizeMode={FastImage.resizeMode.cover}
      style={{ width: 200, height: 200 }}
    />
  );
}

// Caricamento progressivo delle immagini
function ProgressiveImage({ thumbnailUri, fullUri }) {
  const [imageLoaded, setImageLoaded] = useState(false);
  
  return (
    <View>
      <Image
        source={{ uri: thumbnailUri }}
        style={styles.image}
        blurRadius={imageLoaded ? 0 : 5}
      />
      <Image
        source={{ uri: fullUri }}
        style={[styles.image, { opacity: imageLoaded ? 1 : 0 }]}
        onLoad={() => setImageLoaded(true)}
      />
    </View>
  );
}

// Prefetching delle immagini
import { Image } from 'react-native';

const prefetchImages = async (urls) => {
  const promises = urls.map(url => Image.prefetch(url));
  await Promise.all(promises);
};

Rarità: Comune Difficoltà: Media


14. Quali strumenti usi per il performance profiling?

Risposta: Molti strumenti aiutano a identificare i problemi di prestazioni:

  • React DevTools Profiler: Tempi di rendering dei componenti
  • Flipper: Strumento di debug e profiling
  • Performance Monitor: Monitor FPS integrato
  • Systrace: Tracciamento delle prestazioni di Android
  • Instruments: Profiling delle prestazioni di iOS
// Abilita il monitor delle prestazioni in dev
import { LogBox } from 'react-native';

if (__DEV__) {
  // Mostra il monitor delle prestazioni
  require('react-native').unstable_enableLogBox();
}

// Misura il tempo di rendering del componente
import { Profiler } from 'react';

function onRenderCallback(
  id,
  phase,
  actualDuration,
  baseDuration,
  startTime,
  commitTime
) {
  console.log(`${id} (${phase}) ha impiegato ${actualDuration}ms`);
}

function App() {
  return (
    <Profiler id="App" onRender={onRenderCallback}>
      <MyComponent />
    </Profiler>
  );
}

// Tracciamento personalizzato delle prestazioni
const measurePerformance = (name, fn) => {
  const start = performance.now();
  const result = fn();
  const end = performance.now();
  console.log(`${name} ha impiegato ${end - start}ms`);
  return result;
};

Rarità: Comune Difficoltà: Media


Moduli Nativi & Specifico per Piattaforma (4 Domande)

15. Come crei un Modulo Nativo in React Native?

Risposta: I moduli nativi ti permettono di usare codice specifico per la piattaforma.

// iOS (Objective-C) - CalendarManager.m
#import "CalendarManager.h"
#import <React/RCTLog.h>

@implementation CalendarManager

RCT_EXPORT_MODULE();

RCT_EXPORT_METHOD(addEvent:(NSString *)name location:(NSString *)location)
{
  RCTLogInfo(@"Creazione evento %@ in %@", name, location);
}

@end

// Android (Java) - CalendarModule.java
package com.myapp;

import com.facebook.react.bridge.ReactApplicationContext;
import com.facebook.react.bridge.ReactContextBaseJavaModule;
import com.facebook.react.bridge.ReactMethod;

public class CalendarModule extends ReactContextBaseJavaModule {
  CalendarModule(ReactApplicationContext context) {
    super(context);
  }

  @Override
  public String getName() {
    return "CalendarManager";
  }

  @ReactMethod
  public void addEvent(String name, String location) {
    Log.d("CalendarModule", "Creazione evento " + name + " in " + location);
  }
}

// Utilizzo JavaScript
import { NativeModules } from 'react-native';

const { CalendarManager } = NativeModules;

function MyComponent() {
  const createEvent = () => {
    CalendarManager.addEvent('Meeting', 'Office');
  };
  
  return <Button title="Crea Evento" onPress={createEvent} />;
}

Rarità: Media Difficoltà: Alta


16. Come gestisci codice specifico per la piattaforma?

Risposta: Molteplici approcci per codice specifico per la piattaforma:

  1. Modulo Platform: Controlla la piattaforma a runtime
  2. File specifici per la piattaforma: .ios.js e .android.js
  3. Platform.select: Seleziona valori basati sulla piattaforma
import { Platform } from 'react-native';

// Modulo Platform
const styles = StyleSheet.create({
  container: {
    paddingTop: Platform.OS === 'ios' ? 20 : 0,
  },
});

// Platform.select
const styles = StyleSheet.create({
  container: {
    ...Platform.select({
      ios: {
        shadowColor: '#000',
        shadowOffset: { width: 0, height: 2 },
        shadowOpacity: 0.3,
      },
      android: {
        elevation: 4,
      },
    }),
  },
});

// File specifici per la piattaforma
// Button.ios.js
export default function Button() {
  return <Text>Pulsante iOS</Text>;
}

// Button.android.js
export default function Button() {
  return <Text>Pulsante Android</Text>;
}

// Utilizzo - seleziona automaticamente il file corretto
import Button from './Button';

// Controllo della versione della piattaforma
if (Platform.Version >= 21) {
  // Android API 21+
}

Rarità: Molto Comune Difficoltà: Facile


17. Cos'è la Nuova Architettura (Fabric e TurboModules)?

Risposta: La Nuova Architettura migliora le prestazioni di React Native:

  • Fabric: Nuovo sistema di rendering
    • Layout sincrono
    • Migliore interoperabilità con le viste native
    • Type safety
  • TurboModules: Nuovo sistema di moduli nativi
    • Lazy loading
    • JSI (JavaScript Interface) - comunicazione C++ diretta
    • Nessuna serializzazione del bridge

Vantaggi:

  • Avvio più veloce
  • Minore utilizzo di memoria
  • Chiamate native sincrone
  • Migliore type safety

Rarità: Media Difficoltà: Alta


18. Come gestisci il deep linking in React Native?

Risposta: Il deep linking permette di aprire schermate specifiche da URL.

import { Linking } from 'react-native';
import { NavigationContainer } from '@react-navigation/native';

// Configura il deep linking
const linking = {
  prefixes: ['myapp://', 'https://myapp.com'],
  config: {
    screens: {
      Home: 'home',
      Profile: 'profile/:id',
      Settings: 'settings',
    },
  },
};

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

// Gestisci i link in entrata
useEffect(() => {
  const handleUrl = ({ url }) => {
    console.log('Aperto con URL:', url);
    // myapp://profile/123
  };
  
  // App aperta da link
  Linking.getInitialURL().then(url => {
    if (url) handleUrl({ url });
  });
  
  // App già aperta, nuovo link
  const subscription = Linking.addEventListener('url', handleUrl);
  
  return () => subscription.remove();
}, []);

// Apri URL programmaticamente
const openURL = async (url) => {
  const supported = await Linking.canOpenURL(url);
  if (supported) {
    await Linking.openURL(url);
  }
};

Rarità: Comune Difficoltà: Media


Testing (3 Domande)

19. Come testi i componenti React Native?

Risposta: Usa librerie di testing come Jest e React Native Testing Library.

import { render, fireEvent, waitFor } from '@testing-library/react-native';
import Counter from './Counter';

describe('Counter', () => {
  it('renderizza il conteggio iniziale', () => {
    const { getByText } = render(<Counter />);
    expect(getByText('Conteggio: 0')).toBeTruthy();
  });
  
  it('incrementa il conteggio quando si preme il pulsante', () => {
    const { getByText, getByTestId } = render(<Counter />);
Newsletter subscription

Consigli di carriera settimanali che funzionano davvero

Ricevi le ultime idee direttamente nella tua casella di posta

Smetti di Candidarti. Inizia a Essere Assunto.

Trasforma il tuo curriculum in un magnete per colloqui con l'ottimizzazione basata sull'IA di cui si fidano i cercatori di lavoro in tutto il mondo.

Inizia gratis

Condividi questo post

Raddoppia le Tue Chiamate per Colloqui

I candidati che personalizzano il loro curriculum in base alla descrizione del lavoro ottengono 2,5 volte più colloqui. Usa la nostra IA per personalizzare automaticamente il tuo CV per ogni singola candidatura istantaneamente.