javascriptreactjsredux-sagareselect

How to access the latest state in the store using createSelector


This is the first time I'm working with createSelector. I am calling an APi that get all blog-posts from an API https://jsonplaceholder.typicode.com/posts.

I have three actions:

export const GET_POSTS_FETCH = createAction("GET_POSTS_FETCH");
export const GET_POSTS_SUCCESS = createAction("GET_POSTS_SUCCESS");
export const GET_POSTS_FAIL = createAction("GET_POSTS_FAIL");

I have a reducer that is handling the SUCCESS and FAIL cases, which I created using createReducer which upon success successfully adds return state.posts = action.posts; or state.error = action.error; accordingly, where state is initialized with a simple const globalState = {};.

Now the issue I'm facing is when I am creating the selectors. So, I have created the following selectors:

const allPosts = (state) => state.myReducer.posts;
export const selectPosts = createSelector(allPosts, (posts) => posts);

In the UI of my react app I am doing this:

const myDispatch = useDispatch();
const retrivedPosts = useSelector(selectPosts); //Doesn't work
// const retrivedPostsThatWorks = useSelector((state) => state.myReducer.posts); //This works

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

useEffect(() => {
  myDispatch(GET_POSTS_FETCH());
}, []);

I'm dispatching GET_POSTS_FETCH action which in my sagas file getsdata from APi call and upong success the reducer is also storing it accordingly in the store. Now If I take the approach and use retrivedPostsThatWorks I can see the data. But I'm not able to achieve it if I call getAllPosts which I have created using createSelector.

So how do I retrieve the data from a selector created using createSelector?


Solution

  • I think the issue is that you don't have the full path in the allPosts function. Try to replace this:

    const allPosts = (state) => state.posts;
    

    with:

    const allPosts = (state) => state.myReducer.posts;
    

    Update:

    Second issue that you have in your codesandbox is your reducer, specifically this part:

    .addCase(GET_POSTS_SUCCESS, (state, action) => {
      return (state.posts = action.posts);
    })
    

    You should either modify the state or return a new one, but you can't do both. So e.g. simply removing the return will do the trick:

    .addCase(GET_POSTS_SUCCESS, (state, action) => {
      state.posts = action.posts;
    })