MERN Stack 为所有用户显示相同的数据
Posted
技术标签:
【中文标题】MERN Stack 为所有用户显示相同的数据【英文标题】:MERN Stack same data appearing for all users 【发布时间】:2020-07-10 10:21:06 【问题描述】:我正在学习 MERN 堆栈并且我已经完成了该项目,但是我遇到了用户数据问题。当用户创建帐户时,他们可以在经过身份验证后添加项目。这个问题是那些相同的项目出现在另一个用户的仪表板上。我希望用户只看到他们添加的项目。
****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;
****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);
***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);
【问题讨论】:
你需要存储一个用户对应的items
,并获取用户相关的物品。目前,由于您没有在项目中存储任何用户参考,也没有根据请求的用户进行查询,因此您将获得所有项目。
也许在项目中添加一个owner
字段
Uday - 那么我需要将 items.js 文件导入 user.js 文件吗?另外,在 const newItem 内的 item.js 文件中,我是否在其中添加用户?
你可以参考这个猫鼬doc,它解释了文档引用和填充
谢谢你,我去看看。
【参考方案1】:
更新您的项目架构,如下所示
const ItemSchema = new Schema(
name:
type: String,
required: true
,
date:
type:Date,
default: Date.now
,
userId: type: Schema.Types.ObjectId, ref: 'User'
);
您可以使用文档引用或简单地将userId
存储在项目架构中。
在保存项目时使用userId
const newItem = new Item(
name: req.body.name,
userId: req.body.userId
);
在检索项目时,在req
中发送userId
并基于此进行查询
items get route
router.get('/', (req, res) =>
Item.find(userId: req.body.userId )
.sort( date: -1 )
.then(items => res.json(items));
);
如需更多了解,您可以参考此doc 和*** thread
【讨论】:
有什么错误吗?您是否使用 userId 更新了所有旧项目文档? 还有另一个名为 itemReducers.js 的文件,其中包含添加项目、删除项目、获取项目、加载项目的代码。我是否也需要在该文件中更改它? 我猜是的!添加项目时您需要发送userId
我用 itemReducer.js 文件更新了我的帖子。但是,我不认为 userId 会进去,对吧?
我可以知道你在哪里维护当前的用户数据吗?以上是关于MERN Stack 为所有用户显示相同的数据的主要内容,如果未能解决你的问题,请参考以下文章
MERN-stack使用react-router用户身份验证而不使用redux
MERN Stack - Express 和 React 在同一个端口上?