Redux Toolkit Nedir?

609
Redux Toolkit'te slice, belirli bir state dilimi için action'ları, reducer'ları ve başlangıç durumunu tek bir yapı altında toplar. Redux'ta state yönetimini daha organize ve kolay hale getirir.
26 Ağustos 2024 Pazartesi - 10:31 (2 Ay önce)

Redux Toolkit, Redux'u daha kolay ve verimli bir şekilde kullanmamızı sağlayan bir araçtır. Redux Toolkit’in en önemli özelliklerinden biri slice mantığıdır. Slice, Redux’ta state ve reducer’ları bir arada tanımlamayı kolaylaştıran bir yapı sunar.

Slice Nedir?

Bir slice, belirli bir state dilimi için action’ları, reducer’ları ve başlangıç durumunu (initial state) bir arada tanımlar. Redux Toolkit ile oluşturulan bir slice, genellikle bir modülün ya da bir bileşenin state yönetimini kapsar.

Slice Nasıl Çalışır?

edux Toolkit ile slice oluşturmak için createSlice fonksiyonu kullanılır. Bu fonksiyon, reducer, action ve initial state’i tek bir yapı altında toplar.

import { createSlice } from '@reduxjs/toolkit';

// Başlangıç durumu
const initialState = {
  counter: 0,
};

// createSlice ile slice oluşturma
const counterSlice = createSlice({
  name: 'counter',  // Slice'ın adı
  initialState,     // Başlangıç durumu
  reducers: {       // Reducer'lar ve action'lar
    increment: (state) => {
      state.counter += 1;  // state güncellenirken mutasyon yöntemi kullanılabilir
    },
    decrement: (state) => {
      state.counter -= 1;
    },
    incrementByAmount: (state, action) => {
      state.counter += action.payload;
    }
  }
});

// Oluşturulan action'ları ve reducer'ı dışa aktar
export const { increment, decrement, incrementByAmount } = counterSlice.actions;
export default counterSlice.reducer;

Slice Mantığının Faydaları

  1. Kodun Düzenlenmesi: Her bir slice, belirli bir state dilimini yönettiği için kod daha organize hale gelir. Her bileşen ya da modül için ayrı slice'lar oluşturabilirsiniz.

  2. Boilerplate Kodun Azaltılması: Redux Toolkit ile birlikte gelen createSlice, action type tanımlamayı ve reducer yazmayı kolaylaştırır, böylece boilerplate kodu azaltır.

  3. Mutasyon Desteği: createSlice ile yazılan reducer’larda, state’in mutasyon yöntemiyle güncellenmesine izin verilir. Bu, aslında state'in immutability'sini bozmadan yapılır çünkü Redux Toolkit, Immer kütüphanesini kullanarak arka planda bu mutasyonları güvenli hale getirir.

Slice Kullanım Örneği

Redux Toolkit ve slice kullanarak bir sayacı yönetelim:

import { configureStore } from '@reduxjs/toolkit';
import counterReducer from './counterSlice';

// Store oluşturma
const store = configureStore({
  reducer: {
    counter: counterReducer,
  },
});

export default store;

Bileşende Slice Kullanımı

Slice'ı bileşenlerde kullanmak oldukça basittir. Redux Toolkit, useDispatch ve useSelector gibi hook'larla entegrasyonu kolaylaştırır.

import React from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { increment, decrement, incrementByAmount } from './counterSlice';

const CounterComponent = () => {
  const counter = useSelector((state) => state.counter.counter);
  const dispatch = useDispatch();

  return (
    <div>
      <h1>Counter: {counter}</h1>
      <button onClick={() => dispatch(increment())}>Increment</button>
      <button onClick={() => dispatch(decrement())}>Decrement</button>
      <button onClick={() => dispatch(incrementByAmount(5))}>Increment by 5</button>
    </div>
  );
};

export default CounterComponent;

Redux Toolkit’in sunduğu slice mantığı, Redux'u daha kolay ve düzenli hale getirir. State, action ve reducer’ların bir arada tanımlanması, kodun modüler yapıda organize edilmesini sağlar ve boilerplate kodunu azaltır. Özellikle büyük projelerde, slice’lar sayesinde state yönetimi daha yönetilebilir ve okunabilir hale gelir.

initialState, reducers, extraReducers Kavramları

initialState, bir Redux slice'ında ya da reducer'da, uygulamanın başlangıçtaki durumunu tanımlayan nesnedir. Yani, Redux store oluşturulduğunda ya da belirli bir slice ilk kez çalıştırıldığında state'in ne olacağını belirler.

Örneğin, bir sayaç uygulamasında initialState, sayacın başlangıç değerini temsil eder:

const initialState = {
  counter: 0,
};

Bu durumda, counter state'i uygulama başladığında 0 olacak şekilde ayarlanmıştır. Eğer bir kullanıcı increment action'ını dispatch ederse, bu state 1 olarak güncellenir. Ancak, uygulama başladığında veya reducer ilk kez çağrıldığında, initialState bu başlangıç durumunu sağlar.

Kullanım Örneği

const counterSlice = createSlice({
  name: 'counter',
  initialState: { counter: 0 }, // initialState burada tanımlanır
  reducers: {
    increment: (state) => {
      state.counter += 1;
    },
    decrement: (state) => {
      state.counter -= 1;
    },
  },
});

Bu örnekte, initialState, sayacın başlangıç değerini 0 olarak tanımlar. Uygulama başladığında, counter state'i bu başlangıç durumuna sahip olacaktır.

 

Reducers, Redux'ta state'i nasıl değiştireceğimizi tanımlayan saf fonksiyonlardır. Bir action dispatch edildiğinde, ilgili reducer çağrılır ve bu reducer, mevcut state'i alarak belirli bir action'a göre yeni bir state döner. Reducer'lar, gelen action'ı değerlendirir ve buna göre state'i günceller.

Reducer'ın Özellikleri

  1. Saf Fonksiyonlar: Reducer'lar saf (pure) fonksiyonlardır, yani aynı girdiyle her zaman aynı çıktıyı üretirler ve girdiyi (state) mutasyona uğratmazlar.

  2. State Güncellemesi: Reducer, mevcut state ve action'a göre yeni bir state döner. Mevcut state'in doğrudan değiştirilmesi yerine, yeni bir state objesi oluşturulur ve geri döndürülür.

  3. Action'a Dayalı: Reducer'lar, dispatch edilen action'ın type değerine göre belirli işlemler yapar. Her action belirli bir type alanına sahiptir ve reducer'lar bu alanı kontrol ederek ilgili işlemi gerçekleştirir.

Reducer'ın Çalışma Mantığı

Bir action dispatch edildiğinde, Redux store bu action'ı alır ve ilgili reducer'ı çalıştırır. Reducer, action'ın type değerine göre mevcut state'i alır ve yeni bir state döndürür.

const counterReducer = (state = { counter: 0 }, action) => {
    switch (action.type) {
        case 'INCREMENT':
            return { ...state, counter: state.counter + 1 };
        case 'DECREMENT':
            return { ...state, counter: state.counter - 1 };
        default:
            return state; // Tanınmayan bir action'da mevcut state döner
    }
};

Reducer'ın Adımları

  1. Mevcut State ve Action: Reducer, mevcut state ve dispatch edilen action'ı parametre olarak alır.

  2. Action Type Kontrolü: Reducer, action'ın type değerini kontrol eder ve bu değere göre hangi işlemi yapacağını belirler.

  3. Yeni State Döndürme: Reducer, state'i mutasyona uğratmadan, mevcut state'in bir kopyasını oluşturur ve action'a göre güncellemeler yaparak yeni bir state döner.

Reducer'lar, Redux'ta state'in nasıl değişeceğini tanımlayan fonksiyonlardır. Dispatch edilen action'ları alır, bu action'lara göre state'i günceller ve yeni bir state döner. Reducer'lar saf fonksiyonlar oldukları için aynı girdilerle her zaman aynı sonucu üretirler, bu da uygulamanın tahmin edilebilir ve kontrol edilebilir olmasını sağlar.

 

extraReducers, Redux Toolkit'te createSlice fonksiyonu içinde kullanılan ve slice'ın dışında tanımlanan action'ları işlemesini sağlayan bir yapılandırma alanıdır. Normal reducers bölümü, slice içinde tanımlanan action'ları işlerken, extraReducers slice'ın dışındaki action'lara tepki vermek için kullanılır. Bu, özellikle asenkron işlemler (createAsyncThunk ile oluşturulan action'lar gibi) için faydalıdır.

extraReducers Nasıl Çalışır?

Bir slice’ın kendi action'larının dışında başka action'larla da state'i güncellemesi gerektiğinde extraReducers kullanılır. Örneğin, bir slice'ın fulfilled, pending, ve rejected durumlarına göre state'i güncellemesi gerektiğinde extraReducers bölümüne bu action'lar eklenir.

extraReducers Örneği

Aşağıda, bir createAsyncThunk ile oluşturulmuş asenkron bir action ve bunun extraReducers ile bir slice'a nasıl eklendiği gösterilmiştir.

1. Asenkron İşlem Tanımlama (createAsyncThunk)

import { createAsyncThunk, createSlice } from '@reduxjs/toolkit';

// Kullanıcı verilerini getiren asenkron işlem
export const fetchUser = createAsyncThunk(
  'user/fetchUser',
  async (userId) => {
    const response = await fetch(`/api/user/${userId}`);
    return response.json();
  }
);

2. Slice Oluşturma ve extraReducers Kullanımı

const userSlice = createSlice({
  name: 'user',
  initialState: {
    data: null,
    status: 'idle', // 'idle' | 'loading' | 'succeeded' | 'failed'
    error: null
  },
  reducers: {
    // Sadece bu slice'a ait olan action'lar burada tanımlanır
  },
  extraReducers: (builder) => {
    builder
      .addCase(fetchUser.pending, (state) => {
        state.status = 'loading';
      })
      .addCase(fetchUser.fulfilled, (state, action) => {
        state.status = 'succeeded';
        state.data = action.payload;
      })
      .addCase(fetchUser.rejected, (state, action) => {
        state.status = 'failed';
        state.error = action.error.message;
      });
  }
});

export default userSlice.reducer;

extraReducers ve builder Kullanımı

Redux Toolkit’in yeni sürümlerinde extraReducers'ı tanımlarken builder fonksiyonu önerilir. builder kullanımı daha esnek bir yapı sunar ve zincirleme (.addCase) yöntemiyle farklı action'lar eklemeyi sağlar.

extraReducers Ne Zaman Kullanılır?

  • Asenkron İşlemler: createAsyncThunk ile tanımlanan asenkron işlemler için.
  • Dış Action'lar: Bir slice'ın başka bir slice veya modülden gelen action'ları işlemesi gerektiğinde.
  • Ortak State Güncellemeleri: Birden fazla slice'ın aynı action'ı işlemesi gerektiğinde.

extraReducers, bir Redux slice'ın kendi action'ları dışındaki action'ları işlemesini sağlayan bir yapıdır. Bu, özellikle asenkron işlemler ve diğer slice'lardan gelen action'lar için gereklidir. extraReducers, Redux uygulamalarında daha esnek ve modüler bir state yönetimi sağlar.

 


  • React



Yorumlar
Sende Yorumunu Ekle
Kullanıcı
0 karakter