Реагировать на сбой запроса PUT Redux - PullRequest
0 голосов
/ 05 мая 2019

РЕАКТИВНЫЙ запрос Redux PUT выдает мне следующую ошибку: «Ошибка прокси: Не удалось прокси-запрос / api / Stories / 5ccf12b5f6b087c2a3fcc21b от localhost: 3000 до http://localhost:5002. [1] Для получения дополнительной информации см. https://nodejs.org/api/errors.html#errors_common_system_errors(ECONNRESET). "

Я сделал пример CRUD-приложения React Redux на основе учебника @Brad Traversy и запросов GET, POST, DELETE работает нормально.

API с mongoose:

const express = require("express");
const router = express.Router();
const auth = require("../../middleware/auth");

// Item Model
const Item = require("../../models/stories");

// @route   GET api/items
// @desc    Get All Items
// @access  Public
router.get("/", (req, res) => {
  Item.find()
    .sort({ date: -1 })
    .then(items => res.json(items));
});

// @route   POST api/items
// @desc    Create An Item
// @access  Private
router.post("/", auth, (req, res) => {
  const newItem = new Item({
    title: req.body.title,
    body: req.body.body,
    author: "Les Frazier"
  });

  newItem.save().then(item => res.json(item));
});
router.put("/:_id", auth, (req, res) => {
  var query = { _id: req.params._id };
  var update = {
    _id: req.params._id,
    title: req.params.title,
    body: req.params.body
  };
  var options = { new: true, useFindAndModify: false };
  Item.findByIdAndUpdate(req.params._id, { $set: update }, options);
});

// @route   DELETE api/items/:id
// @desc    Delete A 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;

Дочерний компонент для обновления (PUT) сбойных данных

import React, { Component } from "react";
import {
  Button,
  Modal,
  ModalHeader,
  ModalBody,
  Form,
  FormGroup,
  Label,
  Input
} from "reactstrap";
import { connect } from "react-redux";
import { updateStory, deleteStory } from "../../actions/storyActions";
import PropTypes from "prop-types";

class UpdateStoryModal extends Component {
  state = {
    modal: false,
    title: this.props.story.stories.find(
      story => story._id === this.props.value
    ).title,
    body: this.props.story.stories.find(story => story._id === this.props.value)
      .body
  };
  static propTypes = {
    isAuthenticated: PropTypes.bool
  };

  toggle = () => {
    this.setState({
      modal: !this.state.modal
    });
  };

  onChange = e => {
    e.target.name === "title"
      ? this.setState({ title: e.target.value })
      : this.setState({ body: e.target.value });
  };

//PUT
  onSubmit = e => {
    e.preventDefault();

    const updateStory = {
      _id: this.props.value,
      title: this.state.title,
      body: this.state.body
    };

    this.props.updateStory(updateStory);
    // Close modal
    this.toggle();
  };

  render() {
    return (
      <div>
        {this.props.isAuthenticated ? (
          <Button color="primary" size="sm" onClick={this.toggle}>
            Edit Story
          </Button>
        ) : (
          <h4 className="mb-3 ml-4">Please log in to manage stories</h4>
        )}

        <Modal isOpen={this.state.modal} toggle={this.toggle}>
          <ModalHeader toggle={this.toggle}>Edit story</ModalHeader>
          <ModalBody>
            <Form onSubmit={this.onSubmit}>
              <FormGroup>
                <Label for="story">Title</Label>
                <Input
                  type="text"
                  name="title"
                  id="story"
                  onChange={this.onChange}
                  value={this.state.title}
                />
                <Label for="story">Story</Label>
                <Input
                  type="textarea"
                  name="body"
                  rows="20"
                  value={this.state.body}
                  onChange={this.onChange}
                />
                <Button color="dark" style={{ marginTop: "2rem" }} block>
                  Edit story
                </Button>
              </FormGroup>
            </Form>
          </ModalBody>
        </Modal>
      </div>
    );
  }
}

const mapStateToProps = state => ({
  story: state.story,
  title: state.title,
  body: state.body,
  isAuthenticated: state.auth.isAuthenticated
});

export default connect(
  mapStateToProps,
  { updateStory, deleteStory }
)(UpdateStoryModal);

Дочерний компонент, который добавляет (POST) данные и работаетштраф

import React, { Component } from "react";
import {
  Button,
  Modal,
  ModalHeader,
  ModalBody,
  Form,
  FormGroup,
  Label,
  Input
} from "reactstrap";
import { connect } from "react-redux";
import { addStory } from "../../actions/storyActions";
import PropTypes from "prop-types";

class AddStoryModal extends Component {
  state = {
    modal: false,
    title: "",
    body: ""
  };

  static propTypes = {
    isAuthenticated: PropTypes.bool
  };

  toggle = () => {
    this.setState({
      modal: !this.state.modal
    });
  };

  onChange = e => {
    e.target.name === "title"
      ? this.setState({ title: e.target.value })
      : this.setState({ body: e.target.value });
  };

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

    const newStory = {
      title: this.state.title,
      body: this.state.body
    };

    this.props.addStory(newStory);

    // Close modal
    this.toggle();
  };

  render() {
    return (
      <div>
        {this.props.isAuthenticated ? (
          <Button
            color="dark"
            style={{ marginBottom: "2rem" }}
            onClick={this.toggle}
          >
            Add Story
          </Button>
        ) : (
          <h4 className="mb-3 ml-4">Please log in to manage stories</h4>
        )}

        <Modal isOpen={this.state.modal} toggle={this.toggle}>
          <ModalHeader toggle={this.toggle}>Add new story</ModalHeader>
          <ModalBody>
            <Form onSubmit={this.onSubmit}>
              <FormGroup>
                <Label for="story">Title</Label>
                <Input
                  type="text"
                  name="title"
                  id="story"
                  onChange={this.onChange}
                />
                <Label for="story">Story</Label>
                <Input
                  type="textarea"
                  name="body"
                  rows="20"
                  onChange={this.onChange}
                />
                <Button color="dark" style={{ marginTop: "2rem" }} block>
                  Add Story
                </Button>
              </FormGroup>
            </Form>
          </ModalBody>
        </Modal>
      </div>
    );
  }
}

const mapStateToProps = state => ({
  title: state.title,
  body: state.body,
  isAuthenticated: state.auth.isAuthenticated
});

export default connect(
  mapStateToProps,
  { addStory }
)(AddStoryModal);

Редуктор

import {
  GET_STORIES,
  ADD_STORY,
  DELETE_STORY,
  STORIES_LOADING,
  UPDATE_STORY
} from "../actions/types";

const initialState = {
  stories: [],
  loading: false
};

export default function(state = initialState, action) {
  switch (action.type) {
    case GET_STORIES:
      return {
        ...state,
        stories: action.payload,
        loading: false
      };
    case DELETE_STORY:
      return {
        ...state,
        stories: state.stories.filter(story => story._id !== action.payload)
      };
    case ADD_STORY:
      return {
        ...state,
        stories: [action.payload, ...state.stories]
      };
    case UPDATE_STORY:
      return {
        ...state,
        stories: state.stories.map(story =>
          story._id === action.payload._id ? (story = action.payload) : story
        )
      };
    case STORIES_LOADING:
      return {
        ...state,
        loading: true
      };
    default:
      return state;
  }
}

Действие

import axios from "axios";
import {
  GET_STORIES,
  ADD_STORY,
  DELETE_STORY,
  UPDATE_STORY,
  STORIES_LOADING
} from "./types";
import { tokenConfig } from "./authActions";
import { returnErrors } from "./errorActions";

export const getStories = () => dispatch => {
  dispatch(setStoriesLoading());
  axios
    .get("/api/stories")
    .then(res =>
      dispatch({
        type: GET_STORIES,
        payload: res.data
      })
    )
    .catch(err =>
      dispatch(returnErrors(err.response.data, err.response.status))
    );
};

export const addStory = story => (dispatch, getState) => {
  axios
    .post("/api/stories", story, tokenConfig(getState))
    .then(res =>
      dispatch({
        type: ADD_STORY,
        payload: res.data
      })
    )
    .catch(err =>
      dispatch(returnErrors(err.response.data, err.response.status))
    );
};
export const updateStory = story => (dispatch, getState) => {
  axios
    .put(`/api/stories/${story._id}`, story, tokenConfig(getState))
    .then(res =>
      dispatch({
        type: UPDATE_STORY,
        payload: res.data
      })
    )
    .catch(err =>
      dispatch(returnErrors(err.response.data, err.response.status))
    );
};

export const deleteStory = id => (dispatch, getState) => {
  axios
    .delete(`/api/stories/${id}`, tokenConfig(getState))
    .then(res =>
      dispatch({
        type: DELETE_STORY,
        payload: id
      })
    )
    .catch(err =>
      dispatch(returnErrors(err.response.data, err.response.status))
    );
};

export const setStoriesLoading = () => {
  return {
    type: STORIES_LOADING
  };
};

1 Ответ

0 голосов
/ 05 мая 2019

Хорошо, поэтому я нашел основную проблему ...

Я заменил этот код "

  Item.findByIdAndUpdate(req.params._id, { $set: update }, options);

на этот:

  Item.findByIdAndUpdate(
    req.params._id,
    req.body,
    { new: false, useFindAndModify: false },
    () => {
      console.log("done");
    }
  );

И запись идеттеперь обновляется в БД. Таким образом, основная проблема исчезла.

Но всякий раз, когда я обновляю страницу, я все еще получаю следующее: Ошибка прокси: Не удается запросить прокси / api / Stories / 5ccf398fe278beca5efa3d23 от localhost: 3000 до http://localhost:5002. См. https://nodejs.org/api/errors.html#errors_common_system_errors для получения дополнительной информации (ECONNRESET).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...