Reactjs React redux正确更新记录并在屏幕上反映更改

Reactjs React redux正确更新记录并在屏幕上反映更改,reactjs,react-redux,Reactjs,React Redux,出于学习目的,我制作了这个web应用程序,试图在其中实现crud操作。除更新外,所有功能均正常工作,其中MongoDB记录已更新,但屏幕上的更改在刷新之前不会反映出来。 我还在学习,所以不是所有的事情都很清楚,我怀疑减速机有问题。。。或者在组件mapStateToProp对象中 我做错了什么 路线/空气污染指数 Item.findByIdAndUpdate确保更新的db正确,但它是否也应该返回任何内容,以便减速器/操作可以对其作出反应 const express = require("expre

出于学习目的,我制作了这个web应用程序,试图在其中实现crud操作。除更新外,所有功能均正常工作,其中MongoDB记录已更新,但屏幕上的更改在刷新之前不会反映出来。 我还在学习,所以不是所有的事情都很清楚,我怀疑减速机有问题。。。或者在组件mapStateToProp对象中

我做错了什么

路线/空气污染指数 Item.findByIdAndUpdate确保更新的db正确,但它是否也应该返回任何内容,以便减速器/操作可以对其作出反应

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   PUT api/items
// @desc    Update An Item
// @access  Private
router.put("/:_id", auth, (req, res) => {

  Item.findByIdAndUpdate(
    req.params._id,
    req.body,
    { new: false, useFindAndModify: false },
    () => {}
  );
});
module.exports = router;

还原剂

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: action.payload
      };
    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: story
      });
    })
    .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
  };
};

组成部分

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

class UpdateStoryModal extends Component {
  constructor(props) {
    super(props);
  }

  state = {
    id: this.props.idVal,
    modal: false,
    title: this.props.titleVal,
    body: this.props.bodyVal
  };
  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 obj = {
      id: this.props.idVal,
      title: this.state.title,
      body: this.state.body
    };

    this.props.updateStory(obj);
    this.toggle();
  };

  render() {
    return (
      <div>
        {this.props.isAuthenticated ? (
          <button
            type="button"
            className="btn btn-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>
              <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
                  type="button"
                  className="btn btn-dark"
                  style={{ marginTop: "2rem" }}
                  onClick={this.onSubmit}
                >
                  Edit story
                </button>
              </FormGroup>
            </Form>
          </ModalBody>
        </Modal>
      </div>
    );
  }
}

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

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

import React,{Component}来自“React”;
进口{
情态动词
莫达尔海德,
ModalBody,
形式,
FormGroup,
标签,
输入
}从“反应带”;
从“react redux”导入{connect};
从“../../actions/storyActions”导入{UpdateStore}”;
从“道具类型”导入道具类型;
类UpdateStoreModal扩展组件{
建造师(道具){
超级(道具);
}
状态={
id:this.props.idVal,
莫代尔:错,
标题:this.props.titleVal,
body:this.props.bodyVal
};
静态类型={
IsAuthentication:PropTypes.bool
};
切换=()=>{
这是我的国家({
模态:!this.state.modal
});
};
onChange=e=>{
this.setState({[e.target.name]:e.target.value});
};
onSubmit=e=>{
e、 预防默认值();
常量对象={
id:this.props.idVal,
标题:this.state.title,
身体:这个。状态。身体
};
this.props.updateStore(obj);
this.toggle();
};
render(){
返回(
{this.props.isAuthenticated(
编辑故事
) : (
请登录以管理故事
)}
编辑故事
标题
故事
编辑故事
);
}
}
常量mapStateToProps=状态=>({
故事:state.story,
isAuthenticated:state.auth.isAuthenticated
});
导出默认连接(
MapStateTops,
{updateStore}
)(UpdateStoreModal);

是的,您希望从MongoDB数据库返回更新的项目,以便在reducer中使用。看起来您已经设置了动作创建者,以便为该类型的逻辑做好准备。所以我们只需要做几个更新:

在您的快速路线中,您可能需要以下内容:

router.put("/:_id", auth, (req, res) => {
  //this returns a promise
  Item.findByIdAndUpdate(
    req.params._id,
    req.body,
    { new: false, useFindAndModify: false },
    () => {}
  )
  .then((updatedItem) => {
     res.json(updatedItem) //we capture this via our promise-handler on the action
  })
  .catch((error) => {
     return res.status(400).json({ couldnotupdate: "could not update item"})
  })
});
然后,我们可以在action creator promise处理程序中使用
res.data
点击更新的项目

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))
    );
};
现在您已经将更新的项目作为操作负载,我们需要更新您的减速机:

case UPDATE_STORY:
  return {
    ...state,
    stories: state.stories.map((story) => {
        if(story._id == action.payload._id){
           return{
               ...story,
               ...action.payload
           } else {
               return story
           }
       }
    })
  };

这样,您就可以从后端获取更新后的故事,并将其反映到前端。

是的,您希望从MongoDB数据库返回更新后的项目,以便在reducer中使用。看起来您已经设置了动作创建者,以便为该类型的逻辑做好准备。所以我们只需要做几个更新:

在您的快速路线中,您可能需要以下内容:

router.put("/:_id", auth, (req, res) => {
  //this returns a promise
  Item.findByIdAndUpdate(
    req.params._id,
    req.body,
    { new: false, useFindAndModify: false },
    () => {}
  )
  .then((updatedItem) => {
     res.json(updatedItem) //we capture this via our promise-handler on the action
  })
  .catch((error) => {
     return res.status(400).json({ couldnotupdate: "could not update item"})
  })
});
然后,我们可以在action creator promise处理程序中使用
res.data
点击更新的项目

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))
    );
};
现在您已经将更新的项目作为操作负载,我们需要更新您的减速机:

case UPDATE_STORY:
  return {
    ...state,
    stories: state.stories.map((story) => {
        if(story._id == action.payload._id){
           return{
               ...story,
               ...action.payload
           } else {
               return story
           }
       }
    })
  };

这样,您就可以从后端获取最新的故事,并将其反映到前端。

刚刚给您写了一个答案,让我知道这对您的朋友是否有帮助。刚刚给您写了一个答案,让我知道这对您的朋友是否有帮助。