Redux Thunk, Redux için bir ara katman (middleware) kütüphanesidir. Redux'ta, eylemler (actions) genellikle basit JavaScript nesneleridir ve bu nesneler senkronize (synchronous) bir şekilde çalışır. Ancak gerçek dünya uygulamalarında, API çağrıları, zamanlayıcılar gibi zaman alan veya asenkron (asynchronous) işlemlere ihtiyaç duyarız. Redux'ın temel prensipleri gereği, bir eylemin doğrudan bir asenkron işlemi başlatması veya beklemesi mümkün değildir. İşte Redux Thunk bu noktada devreye girer.
Redux Thunk Ne Yapar?
Redux Thunk, action creator'ların (eylem yaratıcılarının) düz bir eylem nesnesi döndürmek yerine bir fonksiyon döndürmesine izin verir. Bu fonksiyona 'thunk' denir. Thunk fonksiyonu, otomatik olarak Redux'ın `dispatch` ve `getState` fonksiyonlarını argüman olarak alır. Bu sayede:
1. Asenkron İşlemleri Yönetme: Thunk içinde, bir API çağrısı yapabilir, bir `setTimeout` kullanabilir veya başka herhangi bir asenkron işlemi gerçekleştirebilirsiniz.
2. Birden Fazla Eylem Gönderme: Asenkron işlemin farklı aşamalarında (örneğin, istek başlatıldığında, veri başarıyla alındığında, bir hata oluştuğunda) birden fazla senkron eylem gönderebilirsiniz (e.g., `FETCH_DATA_REQUEST`, `FETCH_DATA_SUCCESS`, `FETCH_DATA_FAILURE`). Bu, kullanıcı arayüzünde yükleme durumunu, başarı mesajlarını veya hata bildirimlerini göstermek için kritik öneme sahiptir.
3. Mevcut Duruma Erişme: `getState` argümanı sayesinde, asenkron bir işlem yapmadan önce veya yaptıktan sonra Redux mağazasının (store) mevcut durumuna erişebilirsiniz. Bu, belirli bir koşul altında işlem yapmak veya işlemin sonucunu mevcut duruma göre ayarlamak için kullanışlıdır.
Nasıl Çalışır?
Redux Thunk, Redux'ın dispatch mekanizmasının arasına girer. Bir eylem gönderildiğinde:
* Eğer gönderilen eylem bir fonksiyon (thunk) ise, Redux Thunk bu fonksiyonu `dispatch` ve `getState` argümanlarıyla birlikte yürütür.
* Eğer gönderilen eylem düz bir nesne ise, Redux Thunk onu doğrudan Redux'ın temel dispatch işlemine (ve oradan reducer'lara) aktarır.
Avantajları:
* Asenkron logic'i action creator içinde merkezi bir yerde toplar.
* Uygulamanın durumunu yönetme ve yan etkileri ele alma konusunda daha fazla esneklik sağlar.
* Yükleme durumları, başarı ve hata durumları gibi asenkron akışları yönetmek için standart bir yol sunar.
Kurulum: `npm install redux-thunk` veya `yarn add redux-thunk`
Entegrasyon: `applyMiddleware(thunk)` kullanarak Redux store oluştururken Redux'a tanıtılır.
Example Code
```javascript
// src/index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
import { Provider } from 'react-redux';
import store from './store';
import App from './App';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
<React.StrictMode>
<Provider store={store}>
<App />
</Provider>
</React.StrictMode>
);
// src/store.js
import { createStore, applyMiddleware } from 'redux';
import { thunk } from 'redux-thunk'; // v3+ için doğru import
import rootReducer from './reducers';
const store = createStore(rootReducer, applyMiddleware(thunk));
export default store;
// src/reducers/userReducer.js
const initialState = {
users: [],
loading: false,
error: null,
};
const userReducer = (state = initialState, action) => {
switch (action.type) {
case 'FETCH_USERS_REQUEST':
return { ...state, loading: true, error: null };
case 'FETCH_USERS_SUCCESS':
return { ...state, loading: false, users: action.payload };
case 'FETCH_USERS_FAILURE':
return { ...state, loading: false, error: action.payload };
default:
return state;
}
};
export default userReducer;
// src/reducers/index.js
import { combineReducers } from 'redux';
import userReducer from './userReducer';
const rootReducer = combineReducers({
user: userReducer,
// Diğer reducer'lar buraya eklenebilir
});
export default rootReducer;
// src/actions/userActions.js
import axios from 'axios';
// Senkron eylem yaratıcıları
export const fetchUsersRequest = () => ({
type: 'FETCH_USERS_REQUEST',
});
export const fetchUsersSuccess = (users) => ({
type: 'FETCH_USERS_SUCCESS',
payload: users,
});
export const fetchUsersFailure = (error) => ({
type: 'FETCH_USERS_FAILURE',
payload: error,
});
// Bu bir Redux Thunk eylem yaratıcısıdır.
// Düz bir nesne yerine bir fonksiyon döndürür.
export const fetchUsers = () => {
// Bu içteki fonksiyon 'thunk' olarak adlandırılır.
// Redux Thunk middleware tarafından `dispatch` ve `getState` argümanlarıyla çağrılır.
return async (dispatch, getState) => {
// Yükleme durumunu başlatmak için bir eylem gönder
dispatch(fetchUsersRequest());
try {
// Asenkron API çağrısı yap
const response = await axios.get('https://jsonplaceholder.typicode.com/users');
// Başarılı olduğunda veriyi içeren bir eylem gönder
dispatch(fetchUsersSuccess(response.data));
// İsterseniz burada mevcut Redux state'ine de erişebilirsiniz:
// const currentState = getState();
// console.log('Current state after successful fetch:', currentState.user);
} catch (error) {
// Hata durumunda hata mesajını içeren bir eylem gönder
dispatch(fetchUsersFailure(error.message));
}
};
};
// src/App.js
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import { fetchUsers } from './actions/userActions';
function App() {
const dispatch = useDispatch();
// Redux store'dan kullanıcı, yükleme ve hata durumunu seçin
const { users, loading, error } = useSelector((state) => state.user);
useEffect(() => {
// Komponent yüklendiğinde `fetchUsers` thunk'ını dispatch edin
dispatch(fetchUsers());
}, [dispatch]); // `dispatch` bağımlılık olarak eklenmelidir
if (loading) {
return <div style={{ padding: '20px', fontSize: '1.2em' }}>Kullanıcılar yükleniyor...</div>;
}
if (error) {
return <div style={{ padding: '20px', color: 'red', fontSize: '1.2em' }}>Hata: {error}</div>;
}
return (
<div style={{ padding: '20px', fontFamily: 'Arial, sans-serif' }}>
<h1>Kullanıcı Listesi</h1>
{users.length === 0 ? (
<p>Hiç kullanıcı bulunamadı.</p>
) : (
<ul style={{ listStyle: 'none', padding: 0 }}>
{users.map((user) => (
<li
key={user.id}
style={{
marginBottom: '10px',
padding: '10px',
border: '1px solid #eee',
borderRadius: '5px',
backgroundColor: '#f9f9f9'
}}
>
<strong>{user.name}</strong> ({user.email})
</li>
))}
</ul>
)}
</div>
);
}
export default App;
```
Kurulum Adımları (Bu Kodu Çalıştırmak İçin):
1. Yeni bir React projesi oluşturun: `npx create-react-app my-redux-thunk-app`
2. Proje dizinine gidin: `cd my-redux-thunk-app`
3. Gerekli kütüphaneleri yükleyin: `npm install redux react-redux redux-thunk axios` (veya `yarn add redux react-redux redux-thunk axios`)
4. Yukarıdaki kod snippet'larını ilgili dosyalara (örneğin `src/index.js`, `src/store.js`, `src/reducers/userReducer.js`, `src/reducers/index.js`, `src/actions/userActions.js`, `src/App.js`) kopyalayın.
5. Uygulamayı çalıştırın: `npm start` (veya `yarn start`)
Bu örnek, bir API'den kullanıcı verilerini asenkron olarak çeken ve Redux Thunk kullanarak Redux durumunu güncelleyen temel bir React uygulamasını göstermektedir. `fetchUsers` eylem yaratıcısı, verileri getirme isteği başladığında, başarılı olduğunda veya bir hata oluştuğunda ilgili senkron eylemleri gönderen bir thunk döndürür.








redux-thunk