我基本上是新手,只是按照 YouTube 頻道的指導專案進行反應。我已經完成了這個專案的一半。從 app js Form 組件被呼叫,在 Form 組件中,當我點擊提交時,它會呼叫createPost()“client/src/actions/posts.js”中的函式,并且即使其中存在的 async 和 await 關鍵字createPost()沒有異步發布,資料也會被調度。它在 try 塊中顯示錯誤createPost()
無法解構“(中間值)”的屬性“資料”,因為它未定義
但是在 createPost() 內部呼叫了另一個 createPost(),它位于“client/src/api/index.js”中,其中 axios 用于發布資料。當我嘗試在瀏覽器控制臺中控制臺記錄回應時,我得到了
狀態:201 狀態
文本:“已創建”
在此之后,當我重新加載資料時,它會在 UI 中反映出來。我相信這是因為 async 和 await 關鍵字不起作用。在 vscode 中createPosst(),“client/src/actions/posts.js”中的 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
客戶端/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')
);
客戶端/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>
);
}
客戶端/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)
}
}
客戶端/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))};
客戶端/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>
);
}
客戶端/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;
}
}
客戶端/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));
uj5u.com熱心網友回復:
在您中,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);
轉載請註明出處,本文鏈接:https://www.uj5u.com/qukuanlian/385106.html
