Follow

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use
Contact

redux useselector return undefined when i tried to find a value from redux state array according to useParams id

CodeSandbox link

i’m trying to create a demo add post app and it have PostsList.jsx and SinglePostPage.jsx components. I am using redux-toolkit, axios, react-router-dom@6 and JSONplaceholder in this app. Every post section have a View Post Link button to see the full post.

PostList.jsx

MEDevel.com: Open-source for Healthcare and Education

Collecting and validating open-source software for healthcare, education, enterprise, development, medical imaging, medical records, and digital pathology.

Visit Medevel

const PostsList = () => {
  const posts = useSelector((state) => state.posts.entities);
      const renderedPosts = posts.map((post) => (
        <article key={post.id}>
          <h3>{post.title}</h3>
          <p> {post.body.substring(0, 100)} </p>
          <Link to={`posts/${post.id}`}> View Post </Link>
        </article>
      ));
    
      return (
        <section>
          <h2>Posts</h2>
          {renderedPosts}
        </section>
      );
    };

My PostSlice.js File:

const initialState = {
  entities: [],
  status: 'idle',
  error: null,
};

export const fetchPosts = createAsyncThunk('posts/fetchPosts', async () => {
  const response = await axios.get('https://jsonplaceholder.typicode.com/posts');
  return response.data;
});

const postsSlice = createSlice({
  name: 'posts',
  initialState,
  reducers: {
    //omit the reducer functions
  },
  extraReducers(builder) {
    builder
      .addCase(fetchPosts.pending, (state) => {
        state.status = 'loading';
      })
      .addCase(fetchPosts.fulfilled, (state, action) => {
        state.status = 'succeeded';
        state.entities = state.entities.concat(action.payload);
      })
      .addCase(fetchPosts.rejected, (state, action) => {
        state.status = 'failed';
        state.error = action.error.message;
      });
  },
});

I face a problem in SinglePostPage.jsx components.The PostSlist components work properly . But useSelector return undefind when i am trying to get value form redux state array accoring to the id give by useParams hook.

SinglePostPage.jsx

 const SinglePostPage = () => {
      const { postId } = useParams();
      console.log('postId:', postId);
      // postId: 1
      const post = useSelector((state) => state.posts.entities.find(post=> post.id === postId));
      console.log('post:', post);
      // post: undefined
      
      if (!post) {
        return (
          <div>
            <BtnLink to="/">Posts</BtnLink>
            <h1>
              The post doesn't found. Please, go back to the posts section.
            </h1>
          </div>
        );
      }
      return (
        <div>
          <div className="flex justify-between mb-7">
            <BtnLink to="/">Posts</BtnLink>
            <BtnLink to={`/editPost/${postId}`}>Edit Post</BtnLink>
          </div>
          <div>
            <h1>{post.title}</h1>
            <p>{post.body}</p>
          </div>
        </div>
      );
    };
    export default SinglePostPage;

Instead of postId, if i use a integer then i get the value of specific id

const post = useSelector((state) => state.posts.entities.find(post=> post.id === 1));
console.log('post:', post);
// post: {data}

how can i solve this problem…????

>Solution :

The issue is that the route params are always strings and the post id property is a number.

{
  "userId": 1,
  "id": 1, // <-- number type
  "title": "sunt aut facere repellat provident occaecati excepturi optio reprehenderit",
  "body": "quia et suscipit\nsuscipit recusandae consequuntur expedita et cum\nreprehenderit molestiae ut ut quas totam\nnostrum
    rerum est autem sunt rem eveniet architecto"
},

This is why when using a number directly to match (state.posts.entities.find(post=> post.id === 1)) it worked for you.

You are using strict (===) equality when searching for a matching post by id.

const { postId } = useParams();
const post = useSelector((state) =>
  state.posts.entities.find((post) => post.id === postId)
);

post.id is a number and postId is a string, so the equality check returns false because the type is not the same.

To resolve, you could either use loose equality so a type conversion will be done:

const { postId } = useParams();
const post = useSelector((state) =>
  state.posts.entities.find((post) => post.id == postId) // 1 == "1" -> true
);

Or better to convert the post id to a string and keep the strict equality:

const { postId } = useParams();
const post = useSelector((state) =>
  state.posts.entities.find((post) => String(post.id) === postId) // "1" === "1" -> true
);

Edit redux-useselector-return-undefined-when-i-tried-to-find-a-value-from-redux-state

Add a comment

Leave a Reply

Keep Up to Date with the Most Important News

By pressing the Subscribe button, you confirm that you have read and are agreeing to our Privacy Policy and Terms of Use

Discover more from Dev solutions

Subscribe now to keep reading and get access to the full archive.

Continue reading