Server: NodeJS, Express, Mongoose/MongoDB
Cloud provider: MongoDB
Client: React, mobx, axios
Tested with: body-parser, express.json()
Short question: Controller requests data(string) - userId on certain URL from client, but req.body.userId is always undefined. I've checked every component and console logged every step and every react functional component prop - it's okay.
Everything else works fine, such as: find user on sign in/create on sign up, finding posts by id, adding comments to certain post using is id and so all. Already looked up 10-15 questions about this issue, nothing helped. I need to know in which of these files I've been dumb. Thanks in advance!
Additional info:
Part of server/index.js file:
const app = express()
app.use(corsMiddleware)
app.use(express.json()) //also the body-parser returns the same result
app.use('/api/user', userRouter)
CORS middleware:
function cors(req, res, next) {
res.header("Access-Control-Allow-Origin", "*")
res.header("Access-Control-Allow-Methods", "GET, PUT, PATCH, POST, DELETE, OPTIONS")
res.header("Access-Control-Allow-Headers", "Content-Type, Authorization, Origin, X-Requested-With, Accept, X-Auth-Token")
if (req.method === "OPTIONS") {
res.status(200)
}
next()
}
User model:
const {Schema, model} = require('mongoose')
const User = new Schema({
email: {type: String, required: true, unique: true},
login: {type: String, required: true},
password: {type: String, required: true},
link: {type: String, required: true},
avatar: {type: String},
bio: {type: String},
status: {type: String, default: 'offline'},
friends: {type: Array, default: []},
communities: {type: Array, default: []},
requests: {type: Object, default: {
to: [],
from: []
}},
posts: {type: Array, default: []},
settings: {type: Array, default: []},
registrationDate: {type: String, default: Date.now()}
})
module.exports = model('User', User )
Post model:
const {Schema, model} = require('mongoose')
const moment = require('moment')
const Post = new Schema({
title: {type: String, required: true},
content: {type: String, required: true},
userId: {type: ObjectId, required: true, ref: 'User'}, //problem here
login: {type: String, ref: 'User'},
likes: {type: Array, default: []},
dislikes: {type: Array, default: []},
comments: {type: Array, default: []},
date: {type: String, default: () => {
return moment().format('D/MM/YYYY hh:mm')
}}
})
module.exports = model('Post', Post )
Part of userController that gets request:
async getUserById(req, res) {
try {
const {userId} = req.body //tried also const userId = req.body.userId
console.log(userId) //for debugging, output undefined
const user = await User.findById(userId)
res.status(200).json(user)
console.log(user) //for debugging, output null
} catch (e) {
console.log(e) //no errors
}
}
}
Part of user.routes:
router.get('/get', userController.getUserById)
//also deleted the authMiddleware for now, just to make things clean
Client components relations: Feed -> Post -> UserModel
Part of Feed.jsx:
const renderPosts = () => {
return(
posts.map((post) => {
return (
<Post
key={post._id}
username={post.login}
title={post.title}
text={post.content}
likes={post.likes}
dislikes={post.dislikes}
comments={post.comments}
date={post.date}
id={post._id}
userId={post.userId} //problem here
/>
)
})
)
}
Part of Post.jsx:
const [userId, setUserId] = useState('')
useEffect(() => {
console.log(`user id passed from Feed ${props.userId}`) //output OK
setUserId(props.userId)
console.log(`user id as prop in Post ${userId}`) //output OK
}, [props.userId]) //I know I don't need to put it to dependencies, just testing
return (
<div className={styles.Post}>
<div className={styles['post-user']}>
<UserModel userId={userId} username={props.username} link='#'/>
<p className={styles['post-user-title']}>{props.title}</p>
</div>
</div>
)
Part of UserModel.jsx:
export default function UserModel(
{
username,
link,
reverse,
mainUser,
onClick,
comment,
isFriend,
userId
}) {
const handleUsernameClick = async () => {
userPage.fetchUserData(userId)
console.log(`model user id ${userId}`) //output is OK
}
return (
<div className={styles['user-model']}
{//some unnecessary data here with button that calls handleUsernameClick}
</div>
)
}
Part of mobx file that holds fetchUserData method:
class UserPage {
constructor() {
makeAutoObservable(this)
}
//some methods here
fetchUserData = async(userId) => {
try {
const user = await axios.get('http://localhost:5000/api/user/get',
{userId},
{
headers:{Authorization: `Bearer ${localStorage.getItem('token')}`},
})
this.user = user
this.setUserPage(
user.login,
user._id,
user.link,
user.friends,
user.communities
)
console.log(user)
console.log(`user id in store ${userId}`) //output OK
} catch (e) {
console.log(e)
}
}
}
}
export default new UserPage()
CodePudding user response:
to send data, you need to use POST method
change it throughout:
router.post('/get', userController.getUserById)
await axios.post('http://localhost:5000/api/user/get',