React Redux PUT请求失败

时间:2019-05-05 17:13:47

标签: reactjs express mongoose react-redux

REACT Redux PUT请求给我以下错误: “代理错误:无法将localhost:3000的请求/ api / stories / 5ccf12b5f6b087c2a3fcc21b代理到http://localhost:5002。 [1]有关更多信息,请参见https://nodejs.org/api/errors.html#errors_common_system_errors(ECONNRESET)。”

我基于@Brad Traversy教程制作了示例React Redux CRUD应用程序,并且GET,POST,DELETE请求工作正常。

带有猫鼬的API:

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 :(得分:0)

好,所以我发现了主要问题...

我已替换此代码”

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

与此:

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

现在正在db中更新记录。所以主要的问题不见了。

但是,每当刷新页面时,我仍然会得到以下信息: 代理错误:无法将localhost:3000的请求/ api / stories / 5ccf398fe278beca5efa3d23代理到http://localhost:5002。 有关更多信息,请参见https://nodejs.org/api/errors.html#errors_common_system_errors(ECONNRESET)。