当我试图根据 useParams id 从 redux state 数组中找到一个值时,redux useselector return undefined
redux useselector return undefined when i tried to find a value from redux state array according to useParams id
我正在尝试创建一个演示添加 post 应用程序,它有 PostsList.jsx
和 SinglePostPage.jsx
组件。我在此应用程序中使用 redux-toolkit
、axios
、react-router-dom@6
和 JSONplaceholder
。每个 post 部分都有一个 View Post
Link
按钮来查看完整的 post.
PostList.jsx
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>
);
};
我的PostSlice.js文件:
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;
});
},
});
我在 SinglePostPage.jsx
components.The PostSlist
组件正常工作时遇到问题。但是 useSelector
return undefind
当我试图根据 useParams
钩子给出的 id
从 redux 状态数组中获取值时。
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;
而不是 postId
,如果我使用 integer
,那么我会得到特定 id
的值
const post = useSelector((state) => state.posts.entities.find(post=> post.id === 1));
console.log('post:', post);
// post: {data}
我该如何解决这个问题...???
问题是路由参数总是字符串,而 post id
属性 是一个数字。
{
"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"
},
这就是为什么使用数字直接匹配 (state.posts.entities.find(post=> post.id === 1)
) 对您有效。
您在按 ID 搜索匹配项 post 时使用了严格 (===
) 相等性。
const { postId } = useParams();
const post = useSelector((state) =>
state.posts.entities.find((post) => post.id === postId)
);
post.id
是数字,postId
是字符串,所以等式检查returns false,因为类型不一样。
要解决这个问题,您可以使用松散相等来完成类型转换:
const { postId } = useParams();
const post = useSelector((state) =>
state.posts.entities.find((post) => post.id == postId) // 1 == "1" -> true
);
或者更好地将 post id
转换为字符串并保持严格相等:
const { postId } = useParams();
const post = useSelector((state) =>
state.posts.entities.find((post) => String(post.id) === postId) // "1" === "1" -> true
);
我正在尝试创建一个演示添加 post 应用程序,它有 PostsList.jsx
和 SinglePostPage.jsx
组件。我在此应用程序中使用 redux-toolkit
、axios
、react-router-dom@6
和 JSONplaceholder
。每个 post 部分都有一个 View Post
Link
按钮来查看完整的 post.
PostList.jsx
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>
);
};
我的PostSlice.js文件:
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;
});
},
});
我在 SinglePostPage.jsx
components.The PostSlist
组件正常工作时遇到问题。但是 useSelector
return undefind
当我试图根据 useParams
钩子给出的 id
从 redux 状态数组中获取值时。
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;
而不是 postId
,如果我使用 integer
,那么我会得到特定 id
const post = useSelector((state) => state.posts.entities.find(post=> post.id === 1));
console.log('post:', post);
// post: {data}
我该如何解决这个问题...???
问题是路由参数总是字符串,而 post id
属性 是一个数字。
{ "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" },
这就是为什么使用数字直接匹配 (state.posts.entities.find(post=> post.id === 1)
) 对您有效。
您在按 ID 搜索匹配项 post 时使用了严格 (===
) 相等性。
const { postId } = useParams();
const post = useSelector((state) =>
state.posts.entities.find((post) => post.id === postId)
);
post.id
是数字,postId
是字符串,所以等式检查returns false,因为类型不一样。
要解决这个问题,您可以使用松散相等来完成类型转换:
const { postId } = useParams();
const post = useSelector((state) =>
state.posts.entities.find((post) => post.id == postId) // 1 == "1" -> true
);
或者更好地将 post id
转换为字符串并保持严格相等:
const { postId } = useParams();
const post = useSelector((state) =>
state.posts.entities.find((post) => String(post.id) === postId) // "1" === "1" -> true
);