ax ios PUT, данные не обновляются после отправки формы - PullRequest
0 голосов
/ 14 июля 2020

У меня проблема с моим PUT методом. Я использую ax ios и хочу обновить свой «проект». Для этого я использую форму, передаю все данные, и я попадаю на свой маршрут /projects/update/5f0d5f963a82457bc418d03d, где последняя часть - это идентификатор проекта, который я получаю.

Так что в моем компоненте UpdateProject нет ничего особенного:

import React, { Component, Fragment } from 'react';
import axios from 'axios';

import Button from '../../common/Buttons/Button';
import Spinner from '../../common/Spinner/Spinner';

import { API_URL } from '../../../config';
import { isAuthUser } from '../../../utils/utils';

class ProjectUpdate extends Component {
  state = {
    formData: {
      creator: '',
      title: '',
      description: '',
      shortDescription: '',
      photo: '',
      tags: '',
      projectType: '',
      links: {},
    },
    displayLinks: false,
    loading: false,
  };

  componentDidMount() {
    this.ftechId();
  }

  ftechId = async () => {
    this.setState({ loading: true });
    try {
      await axios
        .get(`${API_URL}/projects/${this.props.match.params.projectId}`)
        .then((res) =>
          this.setState({
            formData: res.data,
            loading: false,
          })
        );
    } catch (err) {
      console.log(err);
    }
  };

  updateProject = async (formData) => {
    this.setState({ loading: true });
    const { token } = isAuthUser();
    const config = {
      headers: {
        Accept: 'application/json',
        Authorization: `${token}`,
      },
    };

    try {
      console.log('formdata update', formData);
      await axios
        .put(
          `${API_URL}/projects/update/${this.props.match.params.projectId}`,
          formData,
          config
        )
        .then((res) => console.log('res', res));

      this.setState({ loading: false });
    } catch (err) {
      console.log(err);
    }
  };

  onChange = (e) => {
    // setting formData in the state properly
    const { formData } = this.state;
    let newFormData = { ...formData };
    newFormData[e.target.name] = e.target.value;
    this.setState({
      formData: newFormData,
    });
  };

  onSubmit = (e) => {
    const { formData } = this.state;

    const fileToUpload = document.querySelector('#photoID');
    const sendData = new FormData();

    sendData.append('title', formData.title);
    sendData.append('description', formData.description);
    sendData.append('photo', fileToUpload.files[0]);
    sendData.append('tags', formData.tags);
    sendData.append('projectType', formData.projectType);
    sendData.append('shortDescription', formData.shortDescription);
    sendData.append('git', formData.git);
    sendData.append('demo', formData.demo);
    sendData.append('creator', formData.creator);

    console.log('sendData', formData.tags);

    e.preventDefault();
    this.updateProject(sendData);
  };

  toggleLinks = () => {
    const { displayLinks } = this.state;
    if (!displayLinks) {
      this.setState({ displayLinks: true });
    } else {
      this.setState({ displayLinks: false });
    }
  };

  renderProject = () => {
    const {
      loading,
      displayLinks,
      formData: {
        title,
        description,
        shortDescription,
        photo,
        tags,
        projectType,
        links,
      },
    } = this.state;
    console.log('state form', this.state.formData);
    if (loading === true) {
      return <Spinner />;
    } else {
      return (
        <section className=''>
          <h1 className=''>Update Project</h1>
          <p className=''>
            <i className='fas fa-user'></i> Add project information
          </p>
          <small>* = required field</small>
          <form
            encType='multipart/form-data'
            className='form'
            onSubmit={(e) => this.onSubmit(e)}>
            <div className=''>
              <select
                name='projectType'
                value={projectType}
                onChange={this.onChange}>
                <option value='0'>* Select Project Type Status</option>
                <option value='Front-end'>Front-end</option>
                <option value='Back-end'>Back-end</option>
                <option value='MERN'>MERN</option>
                <option value='Vanila JS'>Vanila JS</option>
                <option value='html'>HTML/CSS</option>
              </select>
              <small className='form-text'>Select a project type.</small>
            </div>
            <div className='form-group'>
              <input
                type='text'
                placeholder='Title'
                name='title'
                value={title}
                onChange={this.onChange}
              />
              <small className='form-text'>Add project title.</small>
            </div>
            <div className='form-group'>
              <input
                type='text'
                placeholder='Description'
                name='description'
                value={description}
                onChange={this.onChange}
              />
              <small className='form-text'>Add project description</small>
            </div>
            <div className='form-group'>
              <input
                type='text'
                placeholder='Short description'
                name='shortDescription'
                value={shortDescription}
                onChange={this.onChange}
              />
              <small className='form-text'>Add project short description</small>
            </div>
            <div className='form-group'>
              <input
                type='text'
                placeholder='* Tags'
                name='tags'
                value={tags}
                onChange={this.onChange}
              />
              <small className='form-text'>
                Please use comma separated values (eg. HTML,CSS,JavaScript,PHP)
              </small>
            </div>
            <div className='form-group'>
              <input
                id='photoID'
                type='file'
                accept='.jpg, .png, .jpeg'
                placeholder='Photo'
                name='photo'
                // value={photo}
                onChange={this.onChange}
              />
              <small className='form-text'>Add project preview.</small>
            </div>
            <div className='my-2'>
              <button onClick={this.toggleLinks} type='button' className=''>
                Add Project Links
              </button>
              <span>Optional</span>

              {displayLinks && (
                <div>
                  <div className=''>
                    <i className=''></i>
                    <input
                      type='text'
                      placeholder='Git URL'
                      name='git'
                      value={links.git}
                      onChange={this.onChange}
                    />
                  </div>

                  <div className=''>
                    <i className=''></i>
                    <input
                      type='text'
                      placeholder='Demo URL'
                      name='demo'
                      value={links.demo}
                      onChange={this.onChange}
                    />
                  </div>
                </div>
              )}
            </div>

            <input type='submit' className='btn btn-primary my-1' />
            <Button className='btn btn-light my-1' to='/projects'>
              Go Back
            </Button>
          </form>
        </section>
      );
    }
  };

  render() {
    return <Fragment>{this.renderProject()}</Fragment>;
  }
}

export default ProjectUpdate;

Здесь я набираю projects/${this.props.match.params.projectId}, чтобы получить данные моего проекта. Я добавляю данные в const sendData = new FormData(); и хочу отправить их на свой mongoDB. Из моего console.logs все данные в состоянии до моего обновления и после обновления. Для обновления я использую этот маршрут:

 updateProject = async (formData) => {
    this.setState({ loading: true });
    const { token } = isAuthUser();
    const config = {
      headers: {
        Accept: 'application/json',
        Authorization: `${token}`,
      },
    };

    try {
      console.log('formdata update', formData);
      await axios
        .put(
          `${API_URL}/projects/update/${this.props.match.params.projectId}`,
          formData,
          config
        )
        .then((res) => console.log('res', res));

      this.setState({ loading: false });
    } catch (err) {
      console.log(err);
    }
  };

Я запутался здесь, потому что из моего ответа, который у меня есть на вкладке «Сеть» на f12, я вижу, что заголовки установлены на новое значение, но сам ответ не изменяется так как мои данные никогда не были snet в db.

Итак, я начинаю копать на моем бэкэнде. В моем маршруте нет ничего особенного

router.put(
  '/projects/update/:projectId',
  authCheck,
  isAdmin,
  findProjectById,
  update
);

Я проверяю здесь, если пользователь является администратором и имеет JWT токен. После того, как я нажал update

exports.update = (req, res) => {
  let form = new formidable.IncomingForm();
  console.log(form);

  form.keepExtensions = true;
  form.parse(req, (err, fields, files) => {
    if (err) {
      return res
        .status(400)
        .json({ errors: [{ msg: 'Image could not be uploaded' }] });
    }

    // const { git, demo } = fields;

    // fields.creator = req.user._id;

    // fields.links = {};
    // if (git) fields.links.git = git;
    // if (demo) fields.links.demo = demo;

    let project = req.project;

    console.log('project', project);
    console.log('req.proj', req.project);

    //1kb = 1000
    //1mb = 1000000kb
    //name 'photo' mus match client side. use photo
    if (files.photo) {
      if (files.photo.size > 1000000) {
        return res.status(400).json({
          errors: [{ msg: 'Image could not be uploaded. File to big.' }],
        });
      }
      //this relates to data in schema product
      project.photo.data = fs.readFileSync(files.photo.path);
      project.photo.contentType = files.photo.type;
    }
    console.log('project update', fields);
    project.save();
    return res.json(project);
  });
};

Здесь из моего console.logs я вижу, что получаю свой проект, когда нажимаю findProjectById, getProject, но похоже, что все останавливается и не движется к update

/* find project by id */

exports.findProjectById = async (req, res, next) => {
  const id = req.params.projectId;
  try {
    let project = await Project.findById(id);
    if (!project) return res.status(400).json({ msg: 'Porject not found' });
    req.project = project;
    next();
  } catch (err) {
    console.error(err.message);
    if (err.kind === 'ObjectId') {
      return res.status(400).json({ msg: 'Porject not found' });
    }
    res.status(500).send('Server Error');
  }
};

Мой req.project возвращает проект, который я хочу обновить, а console.log('proejct update') - это возвращаемые данные, которые я хочу отправить и сохранить, но ничего не происходит. Не уверен, где искать, чтобы это заработало. Я проверял другие похожие проблемы здесь, но у меня ничего не работало

Изменить: после нажатия обновления я получаю ответ 200 для моего PUT, других ошибок нет, но данные не обновлены в БД My ${API_URL}/projects/update/${this.props.match.params.projectId} совпадает с идентификатором моего проекта и маршрутом для обновления

previev

данные формы

1 Ответ

0 голосов
/ 14 июля 2020

Пн goose save возвращает обещание. В бэкэнд-методе update отправьте ответ в блоке then.

...
project.save().then(() => res.json(project))
...
...