【发布时间】: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 maxwidth="lg">
<AppBar className={classes.appBar} position="static" color="inherit">
<Typography className={classes.heading} varient="h2" align="center">
Memories
</Typography>
<img className={classes.image} src={img} alt="memories" height="60" />
</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似乎和我的一样,你能用代码解释一下吗。 -
如果和我的一样应该可以。你能分享你的回购吗?我可以在哪里检查你的整个代码?
标签: reactjs mongodb post async-await