أنت لديك authorsSlice يجلب الكتّاب، إذن لا تحتاج slice جديد.
لكن أيضًا لا نريد فلترة الكتب من booksSlice لأنك تستخدم pagination للكتب، وبالتالي قد لا تكون كل الكتب موجودة في الستور.
إذن الطريقة الأفضل والأبسط في حالتك هي:
استخدم authorsSlice لجلب الكاتب مع كتبه في طلب واحد.
وهذا يتم عبر Strapi:
/authors/:id?populate[books][populate]=imageJavaScriptيعني:
author
├── name
├── image
└── books[]JavaScript1️⃣ تعديل authorsSlice
📁 authorsSlice.js
نضيف thunk جديد:
export const getAuthorDetails = createAsyncThunk(
"authors/getAuthorDetails",
async (authorId) => {
const { data } = await api.get(
`/authors/${authorId}?populate[books][populate]=image`
);
return data.data;
}
);JavaScript2️⃣ إضافة الحالة داخل slice
.addCase(getAuthorDetails.pending, (state) => {
state.isLoading = true;
})
.addCase(getAuthorDetails.fulfilled, (state, action) => {
state.isLoading = false;
// بيانات الكاتب
state.author = action.payload;
// الكتب المرتبطة به
state.books = action.payload.books;
})
.addCase(getAuthorDetails.rejected, (state, action) => {
state.isLoading = false;
state.error = action.error.message;
})JavaScriptويصبح الـ state مثل:
const initialState = {
data: [],
author: null,
books: [],
isLoading: false,
error: null
};JavaScript3️⃣ كارد الكاتب
📁 AuthorCard.jsx
<Link to={`/author/${author.documentId}`}>
<div className="author-card">
<img
src={`http://localhost:1337${author.image?.url}`}
alt={author.name}
/>
<h5>{author.name}</h5>
</div>
</Link>JavaScript4️⃣ Route
<Route
path="/author/:id"
element={<AuthorDetails />}
/>JavaScript5️⃣ صفحة الكاتب
📁 AuthorDetails.jsx
import { useEffect } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useParams } from "react-router-dom";
import { getAuthorDetails } from "../../store/authorsSlice";
import Book from "../../components/Book/Book";
function AuthorDetails(){
const { id } = useParams();
const dispatch = useDispatch();
const { author, books, isLoading } = useSelector(
(state) => state.authors
);
useEffect(()=>{
dispatch(getAuthorDetails(id));
},[dispatch,id]);
if(isLoading){
return <h3>Loading...</h3>;
}
return(
<div className="container my-5">
{/* بيانات الكاتب */}
<div className="text-center mb-5">
<img
src={`http://localhost:1337${author?.image?.url}`}
width="120"
className="rounded-circle"
alt=""
/>
<h2>{author?.name}</h2>
</div>
{/* كتب الكاتب */}
<div className="row row-cols-lg-5">
{books.map((book)=>(
<Book key={book.id} book={book}/>
))}
</div>
</div>
);
}
export default AuthorDetails;JavaScriptماذا يحدث الآن
Author Card
↓
Click
↓
/author/:id
↓
dispatch(getAuthorDetails)
↓
Strapi API
↓
author + books
↓
Redux store
↓
RenderJavaScriptلماذا هذه الطريقة الأفضل لمشروعك
لأنك:
✔ لديك authorsSlice
✔ تستخدم pagination للكتب
✔ تحتاج بيانات الكاتب
✔ تحتاج كتبهJavaScriptوهذه الطريقة تحقق ذلك بطلب API واحد فقط.