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 在同一个端口上?

单击卡片时如何调用函数 - MERN Stack

如何在 MERN 堆栈中向用户显示错误

所有 tableView 单元格为播放列表显示相同的艺术品图像

如何使用 Multer 在 MERN Stack 应用程序中上传图像文件