reactjs - MERN stack MongoDB data
问题描述
I started learning MERN stack and completed a small project. However, the issue I am having is that when a user adds items, those same items appear on another user's dashboard. How can I code it so that the logged-in user only can see his/her data? I am learning a lot about this stack so I would appreciate it if I can get help regarding this issue. Thank you.
****models file Item.js file****
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
//Create Scheme
const ItemSchema = new Schema({
name:{
type: String,
required: true
},
date:{
type:Date,
default: Date.now
}
});
module.exports = Item = mongoose.model('item', ItemSchema);
****model User.js file****
const mongoose = require('mongoose');
const Schema = mongoose.Schema;
//Create Scheme
const UserSchema = new Schema({
name:{
type: String,
required: true,
trim: true,
},
email:{
type: String,
required: true,
unique: true
},
password:{
type: String,
required: true
},
register_date:{
type:Date,
default: Date.now
}
});
module.exports = User = mongoose.model('user', UserSchema);
****api folder item.js code****
const express = require('express');
const router = express.Router();
const auth = require('../../middleware/auth');
//Item model`enter code here`
const Item = require('../../models/Item');
// @route GET api/items
// @description Get All Items
// Access Public
router.get('/', (req, res) =>{
Item.find()
.sort({ date: -1 })
.then(items => res.json(items));
});
// @route POST api/items
// @description Create an item
// Access Private
router.post('/', auth, (req, res) =>{
const newItem = new Item({
name: req.body.name
});
newItem.save().then(item => res.json(item));
});
// @route DELETE api/items/:id
// @description Delete an item
// Access Private
router.delete('/:id', auth, (req, res) =>{
Item.findById(req.params.id)
.then(item => item.remove().then(() => res.json({success:true})))
.catch(err => res.status(404).json({success: false}));
});
module.exports = router;
****api folder user.js code*******
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const config = require('config');
const jwt = require('jsonwebtoken');
//User model
const User = require('../../models/User');
// @route POST api/users
// @description Register new user
// Access Public
router.post('/', (req, res) =>{
const { name, email, password } = req.body;
//Simple validation
if(!name || !email || !password){
return res.status(400).json({ msg:'Please enter all fields' });
}
//Check for existing user
User.findOne({ email })
.then(user => {
if(user) return res.status(400).json({ msg: 'User already exists'});
const newUser = new User({
name,
email,
password
});
//Create salt and hash
bcrypt.genSalt(10, (err, salt) => {
bcrypt.hash(newUser.password, salt, (err, hash) => {
if(err) throw err;
newUser.password = hash;
newUser.save()
.then(user => {
jwt.sign(
{ id: user.id },
config.get('jwtSecret'),
{ expiresIn: 3600 },
(err, token) => {
if(err) throw err;
res.json({
token,
user: {
id: user.id,
name: user.name,
email: user.email
}
});
}
);
});
});
});
});
});
module.exports = router;
****api folder user.js code*******
const express = require('express');
const router = express.Router();
const bcrypt = require('bcryptjs');
const config = require('config');
const jwt = require('jsonwebtoken');
const auth = require('../../middleware/auth');
//User model
const User = require('../../models/User');
// @route POST api/auth
// @description Authenticate the user
// Access Public
router.post('/', (req, res) =>{
const { email, password } = req.body;
//Simple validation
if(!email || !password){
return res.status(400).json({ msg:'Please enter all fields' });
}
//Check for existing user
User.findOne({ email })
.then(user => {
if(!user) return res.status(400).json({ msg: 'User does not exist'});
//Validate password
bcrypt.compare(password, user.password)
.then(isMatch => {
if(!isMatch) return res.status(400).json({ msg: 'Invalid credentials'});
jwt.sign(
{ id: user.id },
config.get('jwtSecret'),
{ expiresIn: 3600 },
(err, token) => {
if(err) throw err;
res.json({
token,
user: {
id: user.id,
name: user.name,
email: user.email
}
});
}
);
});
});
});
// @route GET api/auth/user
// @description Get user data
// Access Private
router.get('/user', auth, (req, res) => {
User.findById(req.user.id)
.select('-password')
.then(user => res.json(user));
});
module.exports = router;
***itemReducer.js file***
import {GET_ITEMS, ADD_ITEM, DELETE_ITEM, ITEMS_LOADING } from '../actions/types';
const initialState = {
items: [],
loading: false
};
export default function(state = initialState, action){
switch(action.type){
case GET_ITEMS:
return{
...state,
items: action.payload,
loading: false
};
case DELETE_ITEM:
return{
...state,
items:state.items.filter(item => item._id !== action.payload)
};
case ADD_ITEM:
return{
...state,
items:[action.payload, ...state.items]
};
case ITEMS_LOADING:
return{
...state,
loading: true
};
default:
return state;
}
}
****ItemModal.js***
import React, { Component } from 'react';
import{
Button,
Modal,
ModalHeader,
ModalBody,
Form,
FormGroup,
Label,
Input
} from 'reactstrap';
import { connect } from 'react-redux';
import { addItem } from '../actions/itemActions';
import PropTypes from 'prop-types';
class ItemModal extends Component{
state = {
modal: false,
name: ''
};
static propTypes = {
isAuthenticated: PropTypes.bool
}
toggle = () =>{
this.setState({
modal: !this.state.modal
});
};
onChange = (e) => {
this.setState({[e.target.name]: e.target.value});
};
onSubmit = (e) =>{
e.preventDefault();
const newItem = {
name: this.state.name
};
//Add item via addItem action
this.props.addItem(newItem);
//Close the Modal
this.toggle();
};
render(){
return(
<div>
{ this.props.isAuthenticated ? <Button
color="dark"
style = {{marginBottom: '2rem'}}
onClick = {this.toggle}
>Add Item</Button> : <h4 className = "mb-3 ml-4"> Please login to manage items</h4> }
<Modal
isOpen = {this.state.modal}
toggle = {this.toggle}>
<ModalHeader toggle={this.toggle}>Add To Shopping List</ModalHeader>
<ModalBody>
<Form onSubmit={this.onSubmit}>
<FormGroup>
<Label for="item">Item</Label>
<Input type="text" name="name" id="item" placeholder="Add Shopping Item" onChange={this.onChange}/>
<Button color="dark" style={{marginTop:'2rem'}} block>Add Item</Button>
</FormGroup>
</Form>
</ModalBody>
</Modal>
</div>
);
}
}
const mapStateToProps = state => ({
item: state.item,
isAuthenticated: state.auth.isAuthenticated
});
export default connect(mapStateToProps, { addItem })(ItemModal);
解决方案
您需要将查询传递给您对集合的.find()
调用,如下所示:Item
Item.find({ query })
现在您的查询为空,默认返回所有文档,请在此处查看。
此外,您还需要为每个项目提供某种用户标识符,我建议将用户的 id 添加到Item
文档中。
推荐阅读
- python - PIL ValueError:使用 alpha_composite 将透明图像绘制到另一个图像上时图像不匹配
- java - 地图
- go-cobra - 根据 flag 指定的目录动态创建 cobra 命令
- linear-programming - 如何解释 cplex 中旅行商问题中的子旅游消除约束?
- java - 启动使用 jpackage 创建的已安装可执行文件时出现 ClassNotFoundException
- string - sed 脚本用换行符替换字符串中的字符串“\n”
- ios - 无法将字符串隐式转换为 CBCharacteristic?
- google-sheets - 如果单元格值存在于不同的列中,则对范围内的单元格进行条件格式设置
- python - 如何让python不多次导入?
- c# - C# - 写入文本文件时,DB 字段中的双空格会导致不需要的换行符