Reactjs React redux正确更新记录并在屏幕上反映更改
出于学习目的,我制作了这个web应用程序,试图在其中实现crud操作。除更新外,所有功能均正常工作,其中MongoDB记录已更新,但屏幕上的更改在刷新之前不会反映出来。 我还在学习,所以不是所有的事情都很清楚,我怀疑减速机有问题。。。或者在组件mapStateToProp对象中 我做错了什么 路线/空气污染指数 Item.findByIdAndUpdate确保更新的db正确,但它是否也应该返回任何内容,以便减速器/操作可以对其作出反应Reactjs React redux正确更新记录并在屏幕上反映更改,reactjs,react-redux,Reactjs,React Redux,出于学习目的,我制作了这个web应用程序,试图在其中实现crud操作。除更新外,所有功能均正常工作,其中MongoDB记录已更新,但屏幕上的更改在刷新之前不会反映出来。 我还在学习,所以不是所有的事情都很清楚,我怀疑减速机有问题。。。或者在组件mapStateToProp对象中 我做错了什么 路线/空气污染指数 Item.findByIdAndUpdate确保更新的db正确,但它是否也应该返回任何内容,以便减速器/操作可以对其作出反应 const express = require("expre
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
}
}
})
};
这样,您就可以从后端获取最新的故事,并将其反映到前端。刚刚给您写了一个答案,让我知道这对您的朋友是否有帮助。刚刚给您写了一个答案,让我知道这对您的朋友是否有帮助。