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
?
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;
})