Wiktor Kujawa
Wiktor Kujawa

Reputation: 619

Adding and deleting two collections with react functional components

I want to add two collections with one action. First one is file using multer and gridfs-stream and second is just literal with properties based on file. That what I achieved: 1)literal based on file and 2)file uploaded. In 1)(literal) this fileID property is just the same as _id of 2)(file) and src in 1) is just filename from 2) concatenated with some path. And here I have to problems. First is that this literal should have more properties, but I have problem with adding them. Here's the model(I think that there's isn't any problem, but it contain all props needed):

const mongoose = require('mongoose');
const Schema = mongoose.Schema;

// Create Schema
const FileSchema = new Schema({
  fileID: {
    type: Schema.Types.ObjectId
  },
  src: {
    type: String,
  },
  altText: {
    type: String,
  },
  caption: {
    type: String,
  },
});

module.exports = File = mongoose.model('file', FileSchema);

The most important GET/POST routes(and also DELETE routes for second problem):

router.get('/', (req, res) => {
  File.find()
    .sort({ date: -1 })
    .then(files => res.json(files))
});
// @route POST /upload
// @desc  Uploads file to DB
router.post('/', upload.single('file'), auth, (req, res) => {
  const newFile = new File({
    fileID: req.file.id,
    src: 'api/files/image/' + req.file.filename,
    altText: 'No image',
    caption: req.body.caption
  })
  newFile.save()

});

// @route GET /files
// @desc  Display all files in JSON
router.get('/', (req, res) => {
  File.find()
    .sort({ date: -1 })
    .then(files => res.json(files))
});

// @route GET /files/:filename
// @desc  Display single file object
router.get('/:filename', (req, res) => {
  gfs.files.findOne({ filename: req.params.filename }, (err, file) => {
    // Check if file
    if (!file || file.length === 0) {
      return res.status(404).json({
        err: 'No file exists'
      });
    }
    // File exists
    return res.json(file);
  });
});

// @route DELETE /files/:id
// @desc  Delete file
router.delete('/:id', auth, (req, res) => {
  gfs.remove({ _id: req.params.id, root: 'files' }, (err, gridStore) => {
    if (err) {
      return res.status(404).json({ err: err });
    }
  });
  File.findById(req.body.fileID)
    .then(file => file.remove().then(() => res.json({ success: true })))
    .catch(err => res.status(404).json({ success: false }));
});

and my React component most important fragments:

const SliderModal = ({ isAuthenticated, addFile }) => {

  const [modal, setModal] = useState(false);
  const [file, setFile] = useState([]);
  const [slideData, setSlideData] = useState({
    fileID: '',
    src: '',
    altText: '',
    caption: '',
  })


  const toggle = () => {
    setModal(!modal);
  };

  const onChange = e => {
    setFile(e.target.files[0]);
    setSlideData({
      ...slideData,
      [e.target.name]: e.target.value
    });
  };

  const onSubmit = e => {
    e.preventDefault();

    const newFile = new FormData();
    newFile.append('file', file);
    // const { src, altText, caption, fileID } = slideData;

    // const newSlide = {
    //   fileID,
    //   src,
    //   altText,
    //   caption
    // }

    // Add file via addItem action
    addFile(newFile);
    // addFile(newSlide);

    // Close modal
    toggle();
  }

and next part(with use of reactstrap):

<Form onSubmit={onSubmit}>
            <FormGroup>
              {/* <Label for="caption">Caption</Label>
              <Input
                type="text"
                name="caption"
                id="caption"
                placeholder="Caption"
                className="mb-3"
                onChange={onChange}
              /> */}

              <Label for="file">File</Label>
              <Input
                type="file"
                name="name"
                id="file"
                placeholder="Add file"
                onChange={onChange}
              />
              <Button
                color="dark"
                style={{ marginTop: '2rem' }}
                block>
                Add File
                </Button>
            </FormGroup>
          </Form>

in which, when I uncomment I have the text input in my modal in which, when I wrote anything I'm getting error:Error while inputting text The second problem is connected with deleting files. At this moment I'm able to delete only one of items(literal or file) from database. Here's DELETE route again: // @route DELETE /files/:id // @desc Delete file router.delete('/:id', auth, (req, res) => { gfs.remove({ _id: req.params.id, root: 'files' }, (err, gridStore) => { if (err) { return res.status(404).json({ err: err }); } }); File.findById(req.body.fileID) .then(file => file.remove().then(() => res.json({ success: true }))) .catch(err => res.status(404).json({ success: false })); });

Okay, I see that File.findById isn't good function, but the problem is that I want to delete them simultaneously. That's why in this literal I concluded that fileID property, but I'm really confused about it and can't find a solution. My idea was to search by this fileID property both and then delete them. Here's react function to delete only file(don't look at that is authenticated, that's just that I can delete file only when I'm logged in my app):

{files.map(({ fileID}) => (
            < CSSTransition key={fileID} timeout={500} classNames="fade" >
              <ListGroupItem>
                {isAuthenticated ?
                  <Button
                    className="remove-btn"
                    color="danger"
                    size="sm"
                    onClick={onDeleteClick.bind(this, fileID)}
                  >&times;
                  </Button> : null}

              </ListGroupItem>
            </CSSTransition>
          ))}

Upvotes: 0

Views: 282

Answers (1)

Wiktor Kujawa
Wiktor Kujawa

Reputation: 619

Ok, I just want to delete two objects with one click.

router.delete('/:id', auth, (req, res) => {
  gfs.remove({ _id: req.params.id, root: 'files' }, (err, gridStore) => {
    if (err) {
      return res.status(404).json({ err: err });
    }
  })
  File.findOne(req.body.fileID)
    .then(file => file.remove().then(() => res.json({ success: true })))
    .catch(err => res.status(404).json({ success: false }));
});

Unfortanelly this one delete two objects, but not compatible. This 'File' object have fileID property, which are the same as id in gfs. My will is to delete two objects with the id == fileID.

Upvotes: 0

Related Questions