Kodax

Hooks المتقدمة — أساسيات React Native

React Hooks المتقدمة

1. useEffect - التأثيرات الجانبية

import { useEffect, useState } from 'react';

function DataFetcher() {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  // يعمل عند تحميل المكون
  useEffect(() => {
    fetchData();
  }, []); // المصفوفة الفارغة = مرة واحدة فقط

  // يعمل عند تغير قيمة معينة
  useEffect(() => {
    console.log('Data changed:', data);
  }, [data]); // يراقب data

  // تنظيف عند إزالة المكون
  useEffect(() => {
    const timer = setInterval(() => {
      console.log('Tick');
    }, 1000);

    return () => {
      clearInterval(timer); // تنظيف
    };
  }, []);

  const fetchData = async () => {
    try {
      const response = await fetch('https://api.example.com/data');
      const json = await response.json();
      setData(json);
    } catch (error) {
      console.error(error);
    } finally {
      setLoading(false);
    }
  };

  if (loading) return <Text>جاري التحميل...</Text>;
  return <Text>{JSON.stringify(data)}</Text>;
}

2. useContext - مشاركة البيانات

import { createContext, useContext, useState } from 'react';

// إنشاء Context
const ThemeContext = createContext();

// Provider
function ThemeProvider({ children }) {
  const [isDark, setIsDark] = useState(false);
  
  const toggleTheme = () => setIsDark(!isDark);

  return (
    <ThemeContext.Provider value={{ isDark, toggleTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// استخدام Context
function ThemedButton() {
  const { isDark, toggleTheme } = useContext(ThemeContext);
  
  return (
    <TouchableOpacity
      onPress={toggleTheme}
      style={{ backgroundColor: isDark ? '#333' : '#fff' }}
    >
      <Text style={{ color: isDark ? '#fff' : '#333' }}>
        {isDark ? '🌙 داكن' : '☀️ فاتح'}
      </Text>
    </TouchableOpacity>
  );
}

// الاستخدام في App
function App() {
  return (
    <ThemeProvider>
      <ThemedButton />
    </ThemeProvider>
  );
}

3. useRef - المراجع

import { useRef, useEffect } from 'react';
import { TextInput, TouchableOpacity, Text } from 'react-native';

function FormWithRef() {
  const inputRef = useRef(null);
  const countRef = useRef(0); // قيمة لا تسبب إعادة رسم

  const focusInput = () => {
    inputRef.current?.focus();
  };

  const incrementCount = () => {
    countRef.current += 1;
    console.log('Count:', countRef.current);
    // لا يسبب إعادة رسم!
  };

  return (
    <View>
      <TextInput ref={inputRef} placeholder="اكتب هنا" />
      <TouchableOpacity onPress={focusInput}>
        <Text>Focus</Text>
      </TouchableOpacity>
    </View>
  );
}

4. useMemo - تحسين الأداء

import { useMemo, useState } from 'react';

function ExpensiveList({ items, filter }) {
  // يُحسب مرة واحدة فقط عند تغير items أو filter
  const filteredItems = useMemo(() => {
    console.log('Filtering...');
    return items.filter(item => 
      item.name.toLowerCase().includes(filter.toLowerCase())
    );
  }, [items, filter]);

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

5. useCallback - تذكر الدوال

import { useCallback, useState } from 'react';

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

  // الدالة تُعاد إنشاؤها فقط عند تغير count
  const handlePress = useCallback(() => {
    setCount(c => c + 1);
  }, []);

  return (
    <View>
      <Text>Count: {count}</Text>
      <ChildComponent onPress={handlePress} />
    </View>
  );
}

// المكون الابن لن يُعاد رسمه بدون سبب
const ChildComponent = React.memo(({ onPress }) => {
  console.log('Child rendered');
  return (
    <TouchableOpacity onPress={onPress}>
      <Text>زيادة</Text>
    </TouchableOpacity>
  );
});

6. Custom Hooks - إنشاء Hooks مخصصة

// useLocalStorage.js
function useAsyncStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(initialValue);
  const [loading, setLoading] = useState(true);

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

  const loadValue = async () => {
    try {
      const value = await AsyncStorage.getItem(key);
      if (value !== null) {
        setStoredValue(JSON.parse(value));
      }
    } catch (error) {
      console.error(error);
    } finally {
      setLoading(false);
    }
  };

  const setValue = async (value) => {
    try {
      setStoredValue(value);
      await AsyncStorage.setItem(key, JSON.stringify(value));
    } catch (error) {
      console.error(error);
    }
  };

  return [storedValue, setValue, loading];
}

// الاستخدام
function App() {
  const [user, setUser, loading] = useAsyncStorage('user', null);
  
  if (loading) return <Text>Loading...</Text>;
  
  return <Text>مرحباً {user?.name}</Text>;
}
اختبر فهمك