A Redux Slice returns undefined

setAllPosts slice returns undefined, data de la api slice imi apare in console log, la al treilea render… Cred ca problema este componenta Blog care este randata inainte ca store sa fie updatat. Am isLoading, deci de ce este allPosts undefined dar data de la api nu este undefined?

import { PayloadAction, createSlice, Slice } from "@reduxjs/toolkit";

export interface Post {
  id: string;
  author: string;
  caption: string;
  title: string;
  image: string;
  body: string;
  category: string;
  tag: string;
  date: string;
}

interface PostState {
  allPosts: Post[];
  filteredPosts: Post[];
  selectedCategory: string | null;
}

const initialState: PostState = {
  allPosts: [] as Post[],
  filteredPosts: [],
  selectedCategory: "",
};

type PostsSlice = Slice<PostState>;

export const postsSlice: PostsSlice = createSlice({
  name: "post",
  initialState,
  reducers: {
    setAllPosts: (state, action: PayloadAction<Post[]>) => {
      console.log("setAllPosts state:", state);
      console.log("setAllPosts action:", action);
      state.allPosts = action.payload;
    },
    filterPostByCategory: (state, action: PayloadAction<string | null>) => {
      state.selectedCategory = action.payload;
      state.filteredPosts = action.payload
        ? state.allPosts.filter((post) => post.category === action.payload)
        : [];
    },
  },
});
console.log("postsSlice:", postsSlice);

export const { setAllPosts, filterPostByCategory } = postsSlice.actions;

export default postsSlice.reducer;
import { createApi, fetchBaseQuery } from "@reduxjs/toolkit/query/react";

export const trainersApi = createApi({
  reducerPath: "trainersApi",
  baseQuery: fetchBaseQuery({ baseUrl: "http://localhost:8000/" }),
  endpoints: (builder) => ({
    getAllTrainers: builder.query({
      query: () => "trainers",
    }),
    getAllTestimonials: builder.query({
      query: () => "testimonials",
    }),
    getAllPosts: builder.query({
      query: () => "posts",
    }),
  }),
});

export const {
  useGetAllTrainersQuery,
  useGetAllTestimonialsQuery,
  useGetAllPostsQuery,
} = trainersApi;
import { combineReducers } from "redux";
import { trainersApi } from "../apiSlice";
import { postsSlice } from "../slices/postFilterSlice";

type RootState = ReturnType<typeof rootReducer>;

const rootReducer = combineReducers({
  [trainersApi.reducerPath]: trainersApi.reducer,
  post: postsSlice.reducer,
});
console.log("rootReducer:", rootReducer);

export default rootReducer;
export type { RootState };
import { useState } from "react";
import MostPopular from "../components/MostPopular";
import NavbarBlog from "../components/NavbarBlog";
import PostPreview from "../components/PostPreview";
import { Fragment } from "react";
import { useGetAllPostsQuery } from "../../features/apiSlice";
import { useDispatch, useSelector } from "react-redux";
import { useEffect } from "react";
import { setAllPosts } from "../../features/slices/postFilterSlice";
import { RootState } from "../../features/reducers";
import { Post } from "../../features/slices/postFilterSlice";

const Blog = () => {
  console.log("Blog component rendered");
  const [displayedPost, setDisplayedPost] = useState(10);
  const { data, error, isError, isLoading } = useGetAllPostsQuery(10);
  const dispatch = useDispatch();
  const postState = useSelector((state: RootState) => state.post);
  const allPosts = useSelector((state: RootState) => state.post?.allPosts);
  const filteredPosts = postState?.filteredPosts;
  const selectedCategory = postState?.selectedCategory;

  useEffect(() => {
    console.log("data:", data);
    if (data) {
      dispatch(setAllPosts(data));
      console.log("dispatched setAllPosts");
    }
  }, [data, dispatch]);

  console.log("allPosts:", allPosts);

  if (isLoading || !allPosts) {
    return <div>Loading...</div>;
  }

  if (isError) {
    console.log("error:", error);
    let errorMessage = "An error occurred";
    if ("message" in error) {
      errorMessage = error.message || "An error occurred";
    } else if ("status" in error) {
      errorMessage = `Error status: ${error.status}` || "An error occurred";
    }
    return <div>Error: {errorMessage}</div>;
  }

  const loadMore = () => {
    setDisplayedPost((prevDisplayedPost) => prevDisplayedPost + 10);
  };

  const postsToShow =
    allPosts &&
    allPosts 
      .filter((post: Post, index: number) => index < displayedPost)
      .map((post: Post, index: number) => (
        <Fragment key={post.id}>
          <PostPreview post={post} />
          {index === 1 && <MostPopular />}
          {index === 1 && (
            <article className="flex flex-col">
              <div className="pt-[75%] relative">
                <img
                  src="./newsletter.jpg"
                  alt=""
                  className="w-full h-full object-cover absolute top-0 left-0"
                />
                <h3 className="p-5 uppercase absolute top-0 left-0 text-white text-left">
                  if you don't want to miss any article, join our newsletter
                </h3>
              </div>
              <div className="pt-[75%] md:pt-0 h-full p-5 relative">
                <img
                  src="./newsletter.jpg"
                  alt=""
                  className="w-full h-full object-cover absolute top-0 left-0"
                />
                <h3 className="p-5 uppercase absolute top-0 left-0 text-white text-left">
                  any article, join our newsletter
                </h3>
                <button className="bg-white text-black border border-black absolute bottom-6">
                  Join Newsletter
                </button>
              </div>
            </article>
          )}
        </Fragment>
      ));

  return (
    <>
      <NavbarBlog />
      <div className="bg-[#e7e7e7] pt-40">
        <header className="text-center md:mt-12 py-8">
          <h1 className="capitalize">
            get the knowledge you need to build the body you want
          </h1>
        </header>
        <div className="p-5">
          <section className="md:grid-cols-2 lg:grid-cols-3 grid grid-cols-1 gap-7 drop-shadow-[0_10px_10px_rgba(0,0,0,0.8)]">
            {postsToShow}
          </section>
          <div className="flex justify-center">
            <button
              className="bg-secondary border border-white text-white my-4"
              onClick={loadMore}
            >
              Load More
            </button>
          </div>
        </div>
      </div>
    </>
  );
};

export default Blog;



Nu reusesc sa ii dau de cap…Daca ma puteti ajuta va rog

Cod cu partea relevanta.
Ca se chioreste omu’ in prins screen uri

Cred ca te-ar ajuta typescript. :smiley:

Aici

const rootReducer = combineReducers({
  stars: starsSlice,
  trainersApi: trainersApi,
  search: searchSlice,
});

vezi ca iti trebuie reducer-ul la fiecare, nu slice-ul in sine.

Adica

const rootReducer = combineReducers({
  stars: starsSlice.reducer,
  [trainersApi.reducerPath]: trainersApi.reducer,
  search: searchSlice.reducer,
});

Aia e faza, ca la genul asta de state management … totul e relevant :sweat_smile: