Redux Toolkit
Redux ile çalışırken yapılandırmalar ve middleware’ler arasında boğuşup duruyorsanız, karşılaştığınız sorunlarda bunun best practice’i nedir diye sürekli düşünüyorsanız Redux Toolkit’e geçmek için iyi bir zaman olabilir.
Redux Toolkit, Redux ve eklentilerini sizler için derleyip, best practice’leri uygulayarak bir araya getiren bir kütüphane.
Redux Toolkit neleri içeriyor?
- Immutable state yönetimi için Immer.
- Selector kütüphanesi olarak Reselect.
- Async işlemler için Redux-thunk. (Redux-saga ile yapılandırabilirsiniz.)
- Debugging için Redux-Devtools.
- Entity Manager olarak createEntityAdapter (@ngrx/entity portu).
Store’un Yapısı
Redux Toolkit’de Store’u yapılandırmak “createStore” a göre oldukça basit. Reducer’ları içeren rootReducer dosyanızı ve varsa custom middleware’ları aşağıdaki şekilde yapılandırabilirsiniz.
import { combineReducers } from '@reduxjs/toolkit'
import subreddit from 'features/subreddit/SubredditSliceAsync'const rootReducer = combineReducers({ subreddit })const store = configureStore({
reducer: rootReducer,
middleware: getDefaultMiddleware({}),
})
Slice’ın Yapısı
Redux mantıksal ifadeleriniz oluşturmak için kullanabileceğiniz standart yöntem createSlice’ı kullanmaktır.
Bir Slice nesnesi, Redux Store’unun bir parçasını (key/value kısmını) temsil eder.
createSlice fonksiyonunun yapısı aşağıdaki gibi:
const subredditSlice = createSlice({name: ‘subreddit’, // slice ismi
initialState, // state’in ilk hali
reducers: { // reducer’lar
getPostsStart: (state) => {
state.loading = true
state.error = null
},
},
})
Slice yapısı ile Action’lar otomatik olarak oluşturuluyor. Action’lara aşağıdaki şekilde erişebilirsiniz.
const { getPostsStart } = subredditSlice.actions
createAsyncThunk’ın Yapısı
Async istekleri yönetmek için standart yöntem createAsyncThunk’ı kullanmaktır.
Async isteklerinizi bu fonksiyonla kullandığınızda Promise’in dönüş durumuna bağlı olarak (pending, fulfilled, rejected) bir action çağırır.
createAsyncThunk type, payloadCreator ve options olmak üzere üç parametre alır.
Örneğin type için ‘subreddit/fetchBySubreddit’ parametresini kullandığımızda bu fonksiyon bize
pending
:'subreddit/fetchBySubreddit/pending'
fulfilled
:'subreddit/fetchBySubreddit/fulfilled'
rejected
:'subreddit/fetchBySubreddit/rejected'
action type’larını oluşturur.
Daha sonra bu action’ları extraReducers içerisinde kullanabiliriz:
extraReducers: (builder) => {
... //fulfilled,pending
builder.addCase(fetchPosts.rejected, (state, action) => {
state.loading = false
state.error = action.payload as string
})
},
Redux Toolkit ile örnek bir uygulama
Redux Toolkit kullanarak seçtiğimiz subreddit ismine göre Reddit.com’dan ilgili forumun iletilerini listeleyen bir örnek yapalım.
Öncelikle ilgili API çağrımızı tanımlayalım:
Slice kullanarak reducer yapısı aşağıdaki gibi tanımlayabiliriz:
Oluşturduğumuz reducer’ları kullandığımız fonksiyon aşağıdaki gibi:
Bu işlem ile “fetchPosts” fonksiyonu bir UI sınıfında kullanılmaya hazır.
Şimdi yukarıdaki örneği createAsyncThunk ile tekrar yazalım.
Gördüğünüz gibi createAsyncThunk kullanarak action’ları kullanmadan işlemi tamamlamış olduk. Yapılan istek Promise’in durumuna göre extraReducers’da bulunan ilgili case’e iletilecek.
Hazırladığımız “fetchPosts” fonksiyonunu UI sınıfında kullanabiliriz.
Uygulamanın kaynak kodlarına https://github.com/akursat/redux-toolkit-example adresinden erişebilirsiniz.