无法在 react-redux 中异步发布
Posted
技术标签:
【中文标题】无法在 react-redux 中异步发布【英文标题】:Not Able to post asynchronously in react-redux 【发布时间】:2022-01-16 08:20:30 【问题描述】:我基本上是刚接触 YouTube 频道的指导项目的新手。
我已经完成了这个项目的一半。
从应用程序 js 调用表单组件,当我单击提交时,它在表单组件中调用“client/src/actions/posts.js”中的createPost()
函数,即使createPost()
中存在 async 和 await 关键字,数据也会被调度它不是异步发布的。它在 createPost()
中的 try 块中显示错误
无法按原样解构“(中间值)”的属性“数据” 未定义
但是在 createPost() 内部调用了另一个 createPost(),它位于“client/src/api/index.js”中,其中 axios 用于发布数据。当我尝试在浏览器控制台中控制台记录响应时,我得到了
状态:201 statusText:"已创建"
在此之后,当我重新加载数据时,它会在 UI 中反映出来。我相信这是因为 async 和 await 关键字不起作用。在 vscode 中,“client/src/actions/posts.js”中的 createPosst()
中的 await 关键字被加下划线并显示 'await' has no effect on the type of this expression.
(请参阅“client/src/actions/posts.js”中的 createPost() 函数) ).我附上了下面的代码文件。谢谢。
客户端文件夹结构
▼ client
> node_modules
> public
▼ src
▼ actions
posts.js
▼ api
index.js
▼ components
▼ Form
Form.js
styles.js
▼ Posts
▼ Post
Post.js
styles.js
Posts.js
styles.js
▼ images
15.png
▼ reducers
index.js
posts.js
App.js
index.js
styles.js
.gitignore
package.json
yarn.lock
client/src/Index.js
import React from "react";
import ReactDOM from "react-dom";
import Provider from "react-redux";
import createStore, applyMiddleware, compose from "redux";
import thunk from "redux-thunk";
import reducers from "./reducers/index";
import App from "./App.js";
const store = createStore(reducers, compose(applyMiddleware(thunk)));
ReactDOM.render(
<Provider store=store>
<App />
</Provider>,
document.getElementById('root')
);
client/src/App.js
import React, useEffect from "react";
import
Container,
AppBar,
Typography,
// Groe,
Grid,
Grow,
from "@material-ui/core";
import useDispatch from 'react-redux';
import getPosts from './actions/posts';
import Posts from "./components/Posts/Posts.js";
import Form from "./components/Form/Form.js";
import useStyles from './styles';
import img from "./images/15.png";
export default function App()
const classes = useStyles();
const dispatch = useDispatch();
useEffect(()=>
dispatch(getPosts());
,[dispatch])
return (
<Container max>
<AppBar className=classes.appBar position="static" color="inherit">
<Typography className=classes.heading varient="h2" align="center">
Memories
</Typography>
<img className=classes.image src=img />
</AppBar>
<Grow in>
<Container>
<Grid
container
justifyContent="space-between"
alignItems="stretch"
spacing=3
>
<Grid item xs=12 sm=7>
<Posts />
</Grid>
<Grid item xs=12 sm=4>
<Form />
</Grid>
</Grid>
</Container>
</Grow>
</Container>
);
client/src/actions/posts.js
import * as api from '../api';
export const getPosts = () => async(dispatch)=>
try
const data = await api.fetchPosts();
dispatch(type:'FETCH_ALL',payload:data);
catch (error)
console.log(error.message);
export const createPost = (post) => async(dispatch) =>
try
//In vscode when i hoover over the below await keyword it shows like below
//'await' has no effect on the type of this expression.
const data = await api.createPost(post)
dispatch(type:'CREATE',payload:data)
catch (error)
console.log(error.message)
client/src/api/index.js
import axios from 'axios';
const url = 'http://localhost:5000/posts';
export const fetchPosts = () => axios.get(url);
export const createPost = (newPost) =>
axios.post(url,newPost).then((res)=>console.log(res));
client/src/components/Form/Form.js
import React, useState from "react";
import TextField, Button, Typography, Paper from "@material-ui/core";
import useStyles from "./styles";
import FileBase from "react-file-base64";
import useDispatch from "react-redux";
import createPost from "../../actions/posts";
export default function Form()
const classes = useStyles();
const dispatch = useDispatch();
const [postData, setPostData] = useState(
creator: "",
title: "",
message: "",
tags: "",
selectedfile: "",
);
const handleSubmit = (e) =>
e.preventDefault();
dispatch(createPost(postData));
;
const clear = () => ;
return (
<Paper className=classes.paper>
<form
autoComplete="off"
noValidate
className=`$classes.root $classes.form`
onSubmit=handleSubmit
>
<Typography variant="h6">creating a Memory</Typography>
<TextField
name="creator"
variant="outlined"
label="Creator"
fullWidth
value=postData.creator
onChange=(e) =>
setPostData( ...postData, creator: e.target.value )
/>
<TextField
name="title"
variant="outlined"
label="Title"
fullWidth
value=postData.title
onChange=(e) => setPostData( ...postData, title: e.target.value )
/>
<TextField
name="message"
variant="outlined"
label="Message"
fullWidth
value=postData.message
onChange=(e) =>
setPostData( ...postData, message: e.target.value )
/>
<TextField
name="tags"
variant="outlined"
label="Tags"
fullWidth
value=postData.tags
onChange=(e) => setPostData( ...postData, tags: e.target.value )
/>
<div className=classes.fileInput>
<FileBase
type="file"
multiple=false
onDone=( base64 ) =>
setPostData( ...postData, selectedFile: base64 )
/>
</div>
<Button
className=classes.buttonSubmit
variant="contained"
color="primary"
size="large"
type="submit"
fullWidth
>
Submit
</Button>
<Button
variant="contained"
color="secondary"
size="small"
onClick=clear
fullWidth
>
clear
</Button>
</form>
</Paper>
);
client/src/reducers/posts.js
export default (posts=[],action) =>
switch (action.type)
case 'FETCH_ALL':
return action.payload;
case 'CREATE':
return [...posts,action.payload];
default:
return posts;
client/src/reducers/index.js
import combineReducers from "redux";
import posts from "./posts";
export const reducers= combineReducers(
posts:posts,
);
服务器文件夹结构
▼ server
▼ controllers
posts.js
▼ models
postMessage.js
> node_modukes
▼ routes
posts.js
index.js
package.json
yarn.lock
服务器/控制器/posts.js
import PostMessage from "../models/postMessage.js";
export const getPosts = async (req, res) =>
try
const postMessages = await PostMessage.find();
res.status(200).json(postMessages);
catch (error)
res.status(400).json( message: error.message );
;
export const createPost = async (req, res) =>
const post = req.body;
const newPost = new PostMessage(post);
try
await newPost.save();
res.status(201).json(newPost);
catch
res.status(409).json( message: error.message );
;
服务器/模型/postMessage.js
import mongoose from 'mongoose';
const postSchema = mongoose.Schema(
title: String,
message: String,
creator: String,
tags: [String],
selectedFile: String,
likeCount:
type: Number,
default: 0,
,
createdAt:
type: Date,
default: new Date(),
,
)
var PostMessage = mongoose.model('PostMessage', postSchema);
export default PostMessage;
服务器/路由/posts.js
import express from "express";
import getPosts, createPost from "../controllers/posts.js";
const router = express.Router();
router.get("/", getPosts);
router.post("/", createPost);
export default router;
服务器/index.js
import express from "express";
import bodyParser from "body-parser";
import mongoose from "mongoose";
import cors from "cors";
import postRoutes from "./routes/posts.js";
const app = express();
app.use(bodyParser.json( limit: "30mb", extended: true ));
app.use(bodyParser.urlencoded( limit: "30mb", extended: true ));
app.use(cors());
app.use("/posts", postRoutes);
const CONNECTION_URL ="...(connection url provided correctly in code)";
const PORT = process.env.PORT || 5000;
mongoose
.connect(CONNECTION_URL, useNewUrlParser: true, useUnifiedTopology: true )
.then(() => app.listen(PORT, () => console.log(`Port:$PORT`)))
.catch((error) => console.log(error.message));
【问题讨论】:
因为您的数据获得了空值,所以您没有返回响应。您需要在此处从 client/src/api/index.js 返回 API 响应 当我尝试返回 api 它显示无法读取控制台中未定义的属性你能用代码解释一下吗 你可以查看我的仓库。我在这里实现了github.com/nazmulweb/simple-mern-blog 我已经检查了你的仓库,但对我来说client/src/api/index.js
似乎和我的一样,你能用代码解释一下吗。
如果和我的一样应该可以。你能分享你的回购吗?我可以在哪里检查你的整个代码?
【参考方案1】:
在您的 client/src/api/index.js
中,您没有返回 API 响应。您需要像这样返回响应
export const createPost = (newPost) =>
return axios.post(url, newPost).then((res)=> res )
;
或
export const createPost = (newPost) => axios.post(url, newPost);
【讨论】:
以上是关于无法在 react-redux 中异步发布的主要内容,如果未能解决你的问题,请参考以下文章
如何使用 thunk 在 react-redux 挂钩中进行异步调用?
react-redux 项目。 Chrome 开发工具不显示所有项目文件