提交数据后useSelector hooks问题
useSelector hooks problem after submitting data
我不确定问题是在 useSelector
还是在 useDispatch
钩子或其他地方,所以情况是这样的:
- 两个屏幕(主屏幕和添加博客屏幕)
- 在
HomeScreen
我点击添加博客按钮然后它重定向到 AddBlogScreen
- 我输入数据,然后提交。提交成功后重定向到
HomeScreen
- 如下图所示,我得到了
no 4
结果,我必须刷新才能得到 no 3
结果。但我的期望是 no 3
图片没有错误。
这是我的代码:
主屏幕
import jwtDecode from "jwt-decode";
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useHistory } from "react-router";
import { blogList } from "../redux/action";
export const MainScreen = () => {
// const [token, setToken] = useState(localStorage.getItem("token"));
const user = jwtDecode(localStorage.getItem("token"));
const history = useHistory();
const dispatch = useDispatch();
useEffect(() => {
dispatch(blogList());
}, [dispatch]);
const { blog } = useSelector((state) => state.blog);
console.log(blog);
return (
<>
<button
onClick={() => {
localStorage.removeItem("token");
history.push("/");
}}
>
singout
</button>
<button
onClick={() => {
history.push({ pathname: "/Blog", state: user });
}}
>
add blog
</button>
<h1 style={{ color: "red" }}>username: {user.username}</h1>
{blog.map(({ id, b_title, b_content, category_id }) => (
<div key={id}>
<h1
onClick={() =>
history.push({
pathname: "/Edit",
state: { id, b_title, b_content, category_id },
})
}
>
Title: {b_title}
</h1>
<p>Content: {b_content}</p>
</div>
))}
</>
);
};
AddBlogScreen
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { useHistory, useLocation } from "react-router";
import { addBlog } from "../redux/action";
export const AddBlogScreen = () => {
const history = useHistory();
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
const [category, setCategory] = useState("");
const dispatch = useDispatch();
const location = useLocation();
const author = location.state.id;
const submitHandler = (e) => {
e.preventDefault();
dispatch(addBlog(title, content, author, category));
setTitle("");
setContent("");
setCategory("");
history.push("/Home");
};
return (
<div>
<h1>add blog page</h1>
<form onSubmit={submitHandler}>
<input
type="text"
placeholder="title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<br />
<br />
<input
type="text"
placeholder="content"
value={content}
onChange={(e) => setContent(e.target.value)}
/>
<br />
<br />
<input
type="text"
placeholder="category"
value={category}
onChange={(e) => setCategory(e.target.value)}
/>
<br />
<br />
<input
type="submit"
value="submit"
disabled={
title === "" || content === "" || category === "" ? true : false
}
/>
</form>
</div>
);
};
动作
import axios from "axios";
import {
LIST_BLOG,
ADD_BLOG,
EDIT_BLOG,
DELETE_BLOG,
LOGIN_USER,
REGISTER_USER,
LOGOUT_USER,
} from "./constant";
// ==================== blog actions ======================
export const blogList = () => async (dispatch) => {
try {
const result = await axios
.get("http://localhost:3001/api/v1/blog?page=0")
.then((res) => res.data.data)
.catch((err) => err);
dispatch({
type: LIST_BLOG,
payload: result,
});
} catch (err) {
dispatch({
payload: err,
});
}
};
export const addBlog =
(title, content, author, category) => async (dispatch) => {
try {
const result = await axios
.post("http://localhost:3001/api/v1/blog", {
blog_title: title,
blog_content: content,
author_id: author,
category_id: category,
})
.then(alert("success add blog"))
.catch((err) => alert(err));
dispatch({
type: ADD_BLOG,
payload: result,
});
} catch (err) {
dispatch({
payload: err,
});
}
};
减速机
const initial_state = {
blog: [],
};
export const blogReducer = (state = initial_state, action) => {
switch (action.type) {
case LIST_BLOG:
return {
...state,
blog: action.payload,
};
case ADD_BLOG:
return {
...state,
blog: action.payload,
};
case EDIT_BLOG:
return {
...state,
blog: action.payload,
};
case DELETE_BLOG:
return {
...state,
blog: action.payload,
};
default:
return state;
}
};
商店
import { blogReducer, userReducer } from "./reducer";
import { combineReducers, createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import thunk from "redux-thunk";
const reducer = combineReducers({
blog: blogReducer,
user: userReducer,
});
const middleWare = composeWithDevTools(applyMiddleware(thunk));
export const store = createStore(reducer, middleWare);
首先错误的来源:
错误说 blog
上名为 map
的 属性 不是函数,意思是 blog
不是数组。
这是它的来源:
const { blog } = useSelector((state) => state.blog);
您的状态是一个带有 属性 命名博客的对象,您可以通过以下两种方式访问它:
const { blog } = useSelector((state) => state);
或
const blog = useSelector((state) => state.blog);
我注意到的其他问题:
在addBlog
中:
1. 当您将 try-catch
与 await
一起使用时,最好也使用 then-catch
。
2.result
不会是您期望的博客数据。它将是一个对象,它是 AxiosResponse
的一个实例,其中包含数据。
您可以通过这种方式从 response
对象中提取 data
:
let response = await axios.post(... // some api request
let {data}=response
我会这样编辑:
export const addBlog =
(title, content, author, category) => async (dispatch) => {
try {
const {data} = await axios
.post("http://localhost:3001/api/v1/blog", {
blog_title: title,
blog_content: content,
author_id: author,
category_id: category,
})
alert("success add blog")
dispatch({
type: ADD_BLOG,
payload: data,
});
} catch (err) {
dispatch({
payload: err,
});
}
};
我找到了解决方案,所以在我的操作中我将其更改为:
dispatch({
type: LIST_BLOG,
payload: result.data.data,
});
我不确定问题是在 useSelector
还是在 useDispatch
钩子或其他地方,所以情况是这样的:
- 两个屏幕(主屏幕和添加博客屏幕)
- 在
HomeScreen
我点击添加博客按钮然后它重定向到AddBlogScreen
- 我输入数据,然后提交。提交成功后重定向到
HomeScreen
- 如下图所示,我得到了
no 4
结果,我必须刷新才能得到no 3
结果。但我的期望是no 3
图片没有错误。
这是我的代码:
主屏幕
import jwtDecode from "jwt-decode";
import React, { useEffect, useState } from "react";
import { useDispatch, useSelector } from "react-redux";
import { useHistory } from "react-router";
import { blogList } from "../redux/action";
export const MainScreen = () => {
// const [token, setToken] = useState(localStorage.getItem("token"));
const user = jwtDecode(localStorage.getItem("token"));
const history = useHistory();
const dispatch = useDispatch();
useEffect(() => {
dispatch(blogList());
}, [dispatch]);
const { blog } = useSelector((state) => state.blog);
console.log(blog);
return (
<>
<button
onClick={() => {
localStorage.removeItem("token");
history.push("/");
}}
>
singout
</button>
<button
onClick={() => {
history.push({ pathname: "/Blog", state: user });
}}
>
add blog
</button>
<h1 style={{ color: "red" }}>username: {user.username}</h1>
{blog.map(({ id, b_title, b_content, category_id }) => (
<div key={id}>
<h1
onClick={() =>
history.push({
pathname: "/Edit",
state: { id, b_title, b_content, category_id },
})
}
>
Title: {b_title}
</h1>
<p>Content: {b_content}</p>
</div>
))}
</>
);
};
AddBlogScreen
import React, { useState } from "react";
import { useDispatch } from "react-redux";
import { useHistory, useLocation } from "react-router";
import { addBlog } from "../redux/action";
export const AddBlogScreen = () => {
const history = useHistory();
const [title, setTitle] = useState("");
const [content, setContent] = useState("");
const [category, setCategory] = useState("");
const dispatch = useDispatch();
const location = useLocation();
const author = location.state.id;
const submitHandler = (e) => {
e.preventDefault();
dispatch(addBlog(title, content, author, category));
setTitle("");
setContent("");
setCategory("");
history.push("/Home");
};
return (
<div>
<h1>add blog page</h1>
<form onSubmit={submitHandler}>
<input
type="text"
placeholder="title"
value={title}
onChange={(e) => setTitle(e.target.value)}
/>
<br />
<br />
<input
type="text"
placeholder="content"
value={content}
onChange={(e) => setContent(e.target.value)}
/>
<br />
<br />
<input
type="text"
placeholder="category"
value={category}
onChange={(e) => setCategory(e.target.value)}
/>
<br />
<br />
<input
type="submit"
value="submit"
disabled={
title === "" || content === "" || category === "" ? true : false
}
/>
</form>
</div>
);
};
动作
import axios from "axios";
import {
LIST_BLOG,
ADD_BLOG,
EDIT_BLOG,
DELETE_BLOG,
LOGIN_USER,
REGISTER_USER,
LOGOUT_USER,
} from "./constant";
// ==================== blog actions ======================
export const blogList = () => async (dispatch) => {
try {
const result = await axios
.get("http://localhost:3001/api/v1/blog?page=0")
.then((res) => res.data.data)
.catch((err) => err);
dispatch({
type: LIST_BLOG,
payload: result,
});
} catch (err) {
dispatch({
payload: err,
});
}
};
export const addBlog =
(title, content, author, category) => async (dispatch) => {
try {
const result = await axios
.post("http://localhost:3001/api/v1/blog", {
blog_title: title,
blog_content: content,
author_id: author,
category_id: category,
})
.then(alert("success add blog"))
.catch((err) => alert(err));
dispatch({
type: ADD_BLOG,
payload: result,
});
} catch (err) {
dispatch({
payload: err,
});
}
};
减速机
const initial_state = {
blog: [],
};
export const blogReducer = (state = initial_state, action) => {
switch (action.type) {
case LIST_BLOG:
return {
...state,
blog: action.payload,
};
case ADD_BLOG:
return {
...state,
blog: action.payload,
};
case EDIT_BLOG:
return {
...state,
blog: action.payload,
};
case DELETE_BLOG:
return {
...state,
blog: action.payload,
};
default:
return state;
}
};
商店
import { blogReducer, userReducer } from "./reducer";
import { combineReducers, createStore, applyMiddleware } from "redux";
import { composeWithDevTools } from "redux-devtools-extension";
import thunk from "redux-thunk";
const reducer = combineReducers({
blog: blogReducer,
user: userReducer,
});
const middleWare = composeWithDevTools(applyMiddleware(thunk));
export const store = createStore(reducer, middleWare);
首先错误的来源:
错误说 blog
上名为 map
的 属性 不是函数,意思是 blog
不是数组。
这是它的来源:
const { blog } = useSelector((state) => state.blog);
您的状态是一个带有 属性 命名博客的对象,您可以通过以下两种方式访问它:
const { blog } = useSelector((state) => state);
或
const blog = useSelector((state) => state.blog);
我注意到的其他问题:
在addBlog
中:
1. 当您将 try-catch
与 await
一起使用时,最好也使用 then-catch
。
2.result
不会是您期望的博客数据。它将是一个对象,它是 AxiosResponse
的一个实例,其中包含数据。
您可以通过这种方式从 response
对象中提取 data
:
let response = await axios.post(... // some api request
let {data}=response
我会这样编辑:
export const addBlog =
(title, content, author, category) => async (dispatch) => {
try {
const {data} = await axios
.post("http://localhost:3001/api/v1/blog", {
blog_title: title,
blog_content: content,
author_id: author,
category_id: category,
})
alert("success add blog")
dispatch({
type: ADD_BLOG,
payload: data,
});
} catch (err) {
dispatch({
payload: err,
});
}
};
我找到了解决方案,所以在我的操作中我将其更改为:
dispatch({
type: LIST_BLOG,
payload: result.data.data,
});