0%

React Hooks: Modern React Geliştirme Rehberi

React Hooks kullanarak daha temiz, daha okunabilir ve daha güçlü React uygulamaları geliştirmeyi öğrenin.

📅
👤CodeBros
⏱️7 dakikada okunur
ReactJavaScriptHooksFrontendWeb
React Hooks: Modern React Geliştirme Rehberi - Blog yazısı öne çıkan görseli

React Hooks: Modern React Geliştirme Rehberi

React Hooks, React 16.8 ile tanıtılan ve React geliştirmede devrim yaratan bir özelliktir. Bu rehberde, Hooks'un tüm yönlerini inceleyecek ve modern React uygulamaları geliştirme becerilerinizi geliştireceksiniz.

React Hooks Nedir?

Hooks, fonksiyonel komponentlerde state ve diğer React özelliklerini kullanmanızı sağlayan fonksiyonlardır. Class component'lere ihtiyaç duymadan React'ın tüm gücünü kullanabilirsiniz.

Hooks'un Avantajları

  • Daha Az Kod: Class syntax'ına gerek yok
  • Daha İyi Kod Organizasyonu: İlgili mantığı birlikte tutma
  • Kolay Test Edilebilirlik: Pure functions daha kolay test edilir
  • Kod Yeniden Kullanımı: Custom Hooks ile mantık paylaşımı

useState: State Yönetimi

En temel Hook olan useState, komponentlerde state tutmayı sağlar.

Temel Kullanım

import { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  
  return (
    <div>
      <p>Sayaç: {count}</p>
      <button onClick={() => setCount(count + 1)}>
        Artır
      </button>
    </div>
  );
}

Nesne ve Dizi State'i

function UserProfile() {
  const [user, setUser] = useState({
    name: '',
    email: '',
    age: 0
  });
  
  const updateName = (name) => {
    setUser(prev => ({
      ...prev,
      name: name
    }));
  };
  
  return (
    <input 
      value={user.name}
      onChange={(e) => updateName(e.target.value)}
    />
  );
}

Lazy Initial State

Pahalı hesaplamalar için lazy initialization:

function ExpensiveComponent() {
  // Bu fonksiyon sadece ilk render'da çalışır
  const [data, setData] = useState(() => {
    const initialData = computeExpensiveValue();
    return initialData;
  });
}

useEffect: Yan Etki Yönetimi

useEffect, component lifecycle'ını yönetmek için kullanılır.

Temel Kullanım

import { useEffect } from 'react';

function DataFetcher() {
  const [data, setData] = useState(null);
  
  useEffect(() => {
    // API çağrısı
    fetch('https://api.example.com/data')
      .then(res => res.json())
      .then(data => setData(data));
  }, []); // Boş dependency array = sadece mount'ta çalış
  
  return <div>{data && JSON.stringify(data)}</div>;
}

Cleanup Fonksiyonu

function WebSocketComponent() {
  useEffect(() => {
    const ws = new WebSocket('ws://localhost:8080');
    
    ws.onmessage = (event) => {
      console.log('Mesaj alındı:', event.data);
    };
    
    // Cleanup: component unmount olduğunda
    return () => {
      ws.close();
    };
  }, []);
}

Dependency Array Best Practices

function SearchComponent() {
  const [query, setQuery] = useState('');
  const [results, setResults] = useState([]);
  
  useEffect(() => {
    if (!query) return;
    
    const timer = setTimeout(() => {
      searchAPI(query).then(setResults);
    }, 500); // Debouncing
    
    return () => clearTimeout(timer);
  }, [query]); // query değiştiğinde çalış
}

useContext: Context API Kullanımı

Global state yönetimi için useContext:

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

// Context oluştur
const ThemeContext = createContext();

// Provider component
function ThemeProvider({ children }) {
  const [theme, setTheme] = useState('light');
  
  return (
    <ThemeContext.Provider value={{ theme, setTheme }}>
      {children}
    </ThemeContext.Provider>
  );
}

// Consumer component
function ThemedButton() {
  const { theme, setTheme } = useContext(ThemeContext);
  
  return (
    <button 
      onClick={() => setTheme(theme === 'light' ? 'dark' : 'light')}
      className={theme}
    >
      Tema: {theme}
    </button>
  );
}

useReducer: Kompleks State Yönetimi

useState'e alternatif olarak, karmaşık state mantığı için:

import { useReducer } from 'react';

const initialState = { count: 0, step: 1 };

function reducer(state, action) {
  switch (action.type) {
    case 'increment':
      return { ...state, count: state.count + state.step };
    case 'decrement':
      return { ...state, count: state.count - state.step };
    case 'setStep':
      return { ...state, step: action.payload };
    case 'reset':
      return initialState;
    default:
      throw new Error();
  }
}

function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  
  return (
    <div>
      <p>Sayaç: {state.count}</p>
      <input 
        value={state.step}
        onChange={(e) => dispatch({ 
          type: 'setStep', 
          payload: Number(e.target.value) 
        })}
      />
      <button onClick={() => dispatch({ type: 'increment' })}>
        +{state.step}
      </button>
      <button onClick={() => dispatch({ type: 'decrement' })}>
        -{state.step}
      </button>
      <button onClick={() => dispatch({ type: 'reset' })}>
        Sıfırla
      </button>
    </div>
  );
}

useRef: DOM Referansları ve Mutable Values

DOM Referansı

import { useRef, useEffect } from 'react';

function FocusInput() {
  const inputRef = useRef(null);
  
  useEffect(() => {
    // Component mount olunca input'a focus
    inputRef.current.focus();
  }, []);
  
  return <input ref={inputRef} type="text" />;
}

Mutable Value Storage

function Timer() {
  const [seconds, setSeconds] = useState(0);
  const intervalRef = useRef(null);
  
  const startTimer = () => {
    intervalRef.current = setInterval(() => {
      setSeconds(s => s + 1);
    }, 1000);
  };
  
  const stopTimer = () => {
    clearInterval(intervalRef.current);
  };
  
  return (
    <div>
      <p>Geçen süre: {seconds}s</p>
      <button onClick={startTimer}>Başlat</button>
      <button onClick={stopTimer}>Durdur</button>
    </div>
  );
}

useMemo ve useCallback: Performance Optimization

useMemo: Expensive Calculations

import { useMemo, useState } from 'react';

function ExpensiveComponent({ items }) {
  const [filter, setFilter] = useState('');
  
  // Sadece items veya filter değiştiğinde yeniden hesapla
  const filteredItems = useMemo(() => {
    console.log('Filtering items...');
    return items.filter(item => 
      item.name.toLowerCase().includes(filter.toLowerCase())
    );
  }, [items, filter]);
  
  return (
    <div>
      <input 
        value={filter}
        onChange={e => setFilter(e.target.value)}
      />
      <ul>
        {filteredItems.map(item => (
          <li key={item.id}>{item.name}</li>
        ))}
      </ul>
    </div>
  );
}

useCallback: Function Memoization

import { useCallback, memo } from 'react';

// Memo ile optimize edilmiş child component
const Button = memo(({ onClick, children }) => {
  console.log('Button rendered:', children);
  return <button onClick={onClick}>{children}</button>;
});

function Parent() {
  const [count, setCount] = useState(0);
  const [other, setOther] = useState(0);
  
  // useCallback olmadan, her render'da yeni fonksiyon
  // useCallback ile, sadece count değişince yeni fonksiyon
  const increment = useCallback(() => {
    setCount(c => c + 1);
  }, []);
  
  return (
    <div>
      <p>Count: {count}</p>
      <p>Other: {other}</p>
      <Button onClick={increment}>Artır Count</Button>
      <button onClick={() => setOther(o => o + 1)}>
        Artır Other
      </button>
    </div>
  );
}

Custom Hooks: Kendi Hook'larınızı Oluşturun

useFetch Hook

function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);
  const [error, setError] = useState(null);
  
  useEffect(() => {
    setLoading(true);
    fetch(url)
      .then(res => res.json())
      .then(data => {
        setData(data);
        setLoading(false);
      })
      .catch(err => {
        setError(err);
        setLoading(false);
      });
  }, [url]);
  
  return { data, loading, error };
}

// Kullanım
function UserProfile({ userId }) {
  const { data, loading, error } = useFetch(`/api/users/${userId}`);
  
  if (loading) return <div>Yükleniyor...</div>;
  if (error) return <div>Hata: {error.message}</div>;
  return <div>{data.name}</div>;
}

useLocalStorage Hook

function useLocalStorage(key, initialValue) {
  const [storedValue, setStoredValue] = useState(() => {
    try {
      const item = window.localStorage.getItem(key);
      return item ? JSON.parse(item) : initialValue;
    } catch (error) {
      console.log(error);
      return initialValue;
    }
  });
  
  const setValue = (value) => {
    try {
      const valueToStore = value instanceof Function 
        ? value(storedValue) 
        : value;
      setStoredValue(valueToStore);
      window.localStorage.setItem(key, JSON.stringify(valueToStore));
    } catch (error) {
      console.log(error);
    }
  };
  
  return [storedValue, setValue];
}

// Kullanım
function App() {
  const [name, setName] = useLocalStorage('name', '');
  
  return (
    <input 
      value={name}
      onChange={e => setName(e.target.value)}
    />
  );
}

React Hooks Best Practices

1. Hook Kuralları

// ✅ DOĞRU: En üst seviyede çağır
function Component() {
  const [state, setState] = useState(0);
  useEffect(() => {}, []);
}

// ❌ YANLIŞ: Koşullu kullanma
function Component() {
  if (condition) {
    const [state, setState] = useState(0); // HATA!
  }
}

2. Dependency Array Doğruluğu

// ✅ DOĞRU: Tüm dependencies belirtilmiş
useEffect(() => {
  console.log(value1, value2);
}, [value1, value2]);

// ❌ YANLIŞ: Eksik dependency
useEffect(() => {
  console.log(value1, value2);
}, [value1]); // value2 eksik!

3. Custom Hook Naming

// ✅ DOĞRU: "use" prefix ile başla
function useCustomHook() {}

// ❌ YANLIŞ: "use" prefix olmadan
function customHook() {} // React bunu Hook olarak tanımaz

Real-World Örnek: Shopping Cart

function useShoppingCart() {
  const [cart, setCart] = useState([]);
  
  const addItem = useCallback((product) => {
    setCart(prev => {
      const existing = prev.find(item => item.id === product.id);
      if (existing) {
        return prev.map(item =>
          item.id === product.id
            ? { ...item, quantity: item.quantity + 1 }
            : item
        );
      }
      return [...prev, { ...product, quantity: 1 }];
    });
  }, []);
  
  const removeItem = useCallback((productId) => {
    setCart(prev => prev.filter(item => item.id !== productId));
  }, []);
  
  const total = useMemo(() => {
    return cart.reduce((sum, item) => 
      sum + (item.price * item.quantity), 0
    );
  }, [cart]);
  
  return { cart, addItem, removeItem, total };
}

function ShoppingCart() {
  const { cart, addItem, removeItem, total } = useShoppingCart();
  
  return (
    <div>
      <h2>Sepetim</h2>
      {cart.map(item => (
        <div key={item.id}>
          <span>{item.name} x {item.quantity}</span>
          <button onClick={() => removeItem(item.id)}>Sil</button>
        </div>
      ))}
      <p>Toplam: {total} TL</p>
    </div>
  );
}

Sonuç

React Hooks, modern React geliştirmede vazgeçilmez bir araçtır. CodeBros olarak projelerimizde:

  • ✅ Hooks-first yaklaşımı benimsiyoruz
  • ✅ Custom Hooks ile kod tekrarını önlüyoruz
  • ✅ Performance optimization için useMemo/useCallback kullanıyoruz
  • ✅ Clean ve maintainable kod yazıyoruz

React projelerinizde profesyonel destek için CodeBros ekibi ile iletişime geçin!


Etiketler: #React #Hooks #JavaScript #Frontend #WebDevelopment #ReactJS #CodeBros

K
CodeBros
CodeBros - Profesyonel Yazılım Geliştirme Şirketi
Paylaş:
WhatsApp
WhatsApp