- بواسطة x32x01 ||
لو بتشتغل React أكيد قابلتك مشكلة Data Fetching
سواء Login، Get Todos، أو أي API Call
دايمًا نفس الأسئلة بتطلع:
createAsyncThunk + extraReducers
createAsyncThunk دي دالة جاهزة في Redux Toolkit
بتستخدمها علشان تعمل Async Logic زي الاتصال بـ API.
أنت بتديها:

RTK بيولّدلك أوتوماتيك 3 حالات:
من غير ما تكتب actions يدوي ولا تتعب نفسك.
جوه createAsyncThunk بيجيلك كائن اسمه thunkAPI
وده بيديك أدوات قوية جدًا
أهمهم:
وده بيخلّي الـ reducer يتعامل مع الخطأ بسهولة.
لما تعمل slice في RTK
هتلاقي مكان اسمه extraReducers
هنا بتقوله:
لو الـ async action دخل في حالة pending أو fulfilled أو rejected
اعمل التغييرات دي في الـ state
كده عندك state ثابت دايمًا فيه: loading - data - error
من جوه أي React Component 
الكومبوننت يقدر:
السبب هو Single Source of Truth 
لو اليوزر عمل Login أي صفحة تانية (Navbar - Profile - Dashboard)
تشوف نفس الداتا من غير Props Drilling
Redux Toolkit خلّى الـ Data Fetching
بعد ما كان صداع في Redux العادي
يبقى 3 خطوات واضحة
عرّف thunk
ضيف extraReducers
استخدم dispatch + selector
أبسط - أنضف - أقوى
سواء Login، Get Todos، أو أي API Call
دايمًا نفس الأسئلة بتطلع:
- أعرف إزاي الطلب بدأ؟ (Loading)

- أحفظ فين الداتا اللي رجعت؟ (Data)

- أتعامل إزاي مع الخطأ؟ (Error)

- وإزاي أخلي الحالة دي متاحة في أي مكان في التطبيق؟

createAsyncThunk + extraReducers
يعني إيه createAsyncThunk؟
createAsyncThunk دي دالة جاهزة في Redux Toolkitبتستخدمها علشان تعمل Async Logic زي الاتصال بـ API.
أنت بتديها:
- اسم للـ action (مثلاً: auth/logIn)
- ودالة فيها منطق الطلب (API Call)
RTK بيولّدلك أوتوماتيك 3 حالات:
- Pending → أول ما الطلب يبدأ
- Fulfilled → لما الطلب ينجح
- Rejected → لما يحصل Error
إيه هو thunkAPI؟
جوه createAsyncThunk بيجيلك كائن اسمه thunkAPIوده بيديك أدوات قوية جدًا
أهمهم:
- dispatch → تبعت actions إضافية
- getState → تجيب الـ state الحالي
- rejectWithValue → أهم حاجة

وده بيخلّي الـ reducer يتعامل مع الخطأ بسهولة.
استخدام extraReducers في Redux Toolkit
لما تعمل slice في RTKهتلاقي مكان اسمه extraReducers
هنا بتقوله:
لو الـ async action دخل في حالة pending أو fulfilled أو rejected
اعمل التغييرات دي في الـ state
مثال عملي:
- pending
- loading = true
- مسح أي error قديم
- fulfilled
- loading = false
- تخزين الداتا (user / token)
- rejected
- loading = false
- تخزين رسالة الخطأ
مثال كود عملي (Redux Toolkit)
JavaScript:
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit';
import axios from 'axios';
export const logIn = createAsyncThunk(
'auth/logIn',
async (userData, thunkAPI) => {
try {
const res = await axios.post('/api/login', userData);
return res.data;
} catch (err) {
return thunkAPI.rejectWithValue(err.response.data.message);
}
}
);
const authSlice = createSlice({
name: 'auth',
initialState: {
loading: false,
user: null,
error: null,
},
extraReducers: (builder) => {
builder
.addCase(logIn.pending, (state) => {
state.loading = true;
state.error = null;
})
.addCase(logIn.fulfilled, (state, action) => {
state.loading = false;
state.user = action.payload;
})
.addCase(logIn.rejected, (state, action) => {
state.loading = false;
state.error = action.payload;
});
},
});
export default authSlice.reducer;
إزاي أستخدمه جوه الكومبوننت؟
من جوه أي React Component - تستخدم useDispatch علشان تبعت الـ thunk
- تستخدم useSelector علشان تقرا الـ state
JavaScript:
const dispatch = useDispatch();
const { loading, user, error } = useSelector(state => state.auth);
const handleLogin = () => {
dispatch(logIn(formData));
}; - يعرض Loading... أثناء الطلب

- يطلع رسالة خطأ

- يعرض بيانات اليوزر لما الـ login ينجح

ليه الـ state متاح في كل الكومبوننتات؟
السبب هو Single Source of Truth - الـ Redux Store متحطوط في <Provider>
- أي كومبوننت تحته يقدر يوصل لنفس الـ state
لو اليوزر عمل Login أي صفحة تانية (Navbar - Profile - Dashboard)
تشوف نفس الداتا من غير Props Drilling
النتيجة النهائية
- createAsyncThunk → إدارة الـ async بسهولة
- extraReducers → تحكم في Loading / Data / Error
- dispatch + useSelector → تعامل بسيط من الكومبوننت
- State مركزي متاح في أي مكان
الخلاصة
Redux Toolkit خلّى الـ Data Fetchingبعد ما كان صداع في Redux العادي
يبقى 3 خطوات واضحة