reactjs - React,如何在 axios PUT 请求后更新组件
问题描述
我正在尝试为我的问题找到解决方案。情况是这样的:我有一个 EducationComponent,其中包含 GET 请求(使用 axios),然后返回所有教育数组的 .map,但是 .map 创建的每个项目的渲染都在另一个组件中,即 EducationItemComponent,它包含一个带有表单的折叠,您可以使用 PUT 请求(使用 axios 制作)在数据库中编辑该项目。
一切都运行良好,即使我确信我制造了很多混乱并且肯定会是一些更简单的方法来实现我的应用程序,但我对 React 和 JSX 非常陌生,这是我现在能做的最大的事情。
我要做的是:一旦我填写了表格并提交了它,并且 PUT 请求更改了我数据库中的数据,我想重新渲染该项目并立即查看我的更改已经完成了,但我找不到任何方法来做到这一点。
以下是 EducationComponent 中的代码:
import React, { useEffect } from 'react';
import { useSelector, useDispatch } from 'react-redux';
import axios from 'axios';
import { addEducation } from '../../redux/actions/educationActions';
import { EducationItem } from './EducationItemComponent';
export const Education = () => {
const education = useSelector((state) => state.education.education);
const { id, school, date, description } = education ?? {};
const dispatch = useDispatch();
const fetchEducation = async (id, school, date, descr) => {
const response = await axios
.get('http://localhost:3005/education')
.catch((err) => {
console.log('Err', err);
});
dispatch(addEducation(response.data));
console.log(response.data[0].school);
}
useEffect(() => {
fetchEducation();
}, []);
return (
<div className="education clearfix">
<h2 className="small-heading">EDUCATION</h2>
<div className="education-container col-lg-10 col-lg-offset-1 col-md-12 col-md-offset-0 col-sm-10 col-sm-offset-1">
{ /* Education items */}
{education.map(educ =>
<>
<EducationItem key={educ.id} id={educ.id} school={educ.school} descr={educ.description} date={educ.date} />
</>
)}
</div>
</div>
);
}
这是 EducationItemComponent 的代码,它从 .map 中渲染每个组件:
import React from 'react';
import { Collapse } from 'reactstrap';
import { ButtonGroup, Button, Form } from 'react-bootstrap';
import { faEdit, faTrashAlt } from '@fortawesome/free-solid-svg-icons';
import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import axios from 'axios';
const putEducation = async (id, school, date, descr) => {
var educUrl = 'http://localhost:3005/education/' + id;
const newEducation = {
id: id,
school: school,
date: date,
description: descr
}
const response = await axios
.put(educUrl, newEducation)
.catch((err) => {
console.log('Err', err);
});
}
const submitEducationEdit = (event, id, success) => {
event.preventDefault();
putEducation(id, event.target.school.value, event.target.date.value, event.target.description.value);
}
export class EducationItem extends React.Component {
constructor(props) {
super(props);
this.toggle = this.toggle.bind(this);
this.state = {
open: false
};
}
toggle() {
this.setState({ open: !this.state.open });
}
render() {
return (
<>
<div className="item" key={this.props.id}>
<div className="bullet hidden-xs">
</div>
<div className="education-content">
<h3>{this.props.school}<span> / {this.props.date}</span></h3>
<p>
{this.props.descr}
</p>
</div>
<div className="edit">
<ButtonGroup vertical>
<Button onClick={this.toggle} variant="success"><FontAwesomeIcon icon={faEdit} /></Button>
<Button variant="danger"><FontAwesomeIcon icon={faTrashAlt} /></Button>
</ButtonGroup>
</div>
</div>
<Collapse isOpen={this.state.open}>
<Form onSubmit={(e) => submitEducationEdit(e, this.props.id, this.state.success)} id="educationEditFormId">
<Form.Row>
<Form.Group className={"half"}>
<Form.Label>School</Form.Label>
<Form.Control
name="school"
as="textarea"
rows={1} />
</Form.Group>
<Form.Group className={"half"}>
<Form.Label>Date</Form.Label>
<Form.Control
name="date"
as="textarea"
rows={1} />
</Form.Group>
</Form.Row>
<Form.Group>
<Form.Label>Description</Form.Label>
<Form.Control
name="description"
as="textarea"
rows={5} />
</Form.Group>
<Button
variant="success"
type="submit"
size="sm" >
Submit
</Button>
</Form>
</Collapse>
</>
);
}
}
我还尝试在educationReducer 中编写putEducation 和fetchEducation 常量(我使用Redux 来管理我的商店),但是我不能使用例如useDispatch() 挂钩,因为我不能在顶层使用它,而且我找不到使用它的方法,我不知道是否有另一种方法来调度我从 axios GET 请求中获得的响应。如果我可以在educationReducer 中编写它们,那可能会更容易,因为我可以从我的两个组件中调用它们,然后使用 useEffect 挂钩来刷新项目,或者类似的东西。我真的不知道如何解决这个问题,什么是最好的方法。
提前谢谢你们。
这是我现在的educationActions的样子:
import * as ActionTypes from '../constants/ActionTypes';
export const addEducation = (education) => {
return {
type: ActionTypes.ADD_EDUCATION,
payload: education
};
};
这是educationReducer:
import * as ActionTypes from '../constants/ActionTypes';
const initialState = {
education: [],
}
export const educationReducer = (state = initialState, { type, payload }) => {
switch (type) {
case ActionTypes.ADD_EDUCATION:
return { ...state, education: payload };
default:
return state;
}
}
解决方案
推荐阅读
- jasper-reports - 当详细信息部分中有两个波段时,如何强制第一个详细信息波段打印在页面顶部?
- robotframework - 如何使用 Robot Framework RESTinstance 库验证 JSON 结果
- mysql - 动态创建表时如何避免SQL注入风险?
- python - 从 Django 1.8 升级到 1.9 时出现 ValueError
- reactjs - 如何从不是主应用程序页面的页面路由到另一个页面
- c - C 代码的问题,在 10 月的最后一个星期日更改标志以进行夏令时
- graphql - 嵌套的 Graphql 输入对象类型
- r - 如何找到非线性回归模型的起始值?
- facebook - 为什么在调用 FB.logout() 并刷新页面后我看不到 FB 登录屏幕?
- java - 处理聊天活动中的图像视图位置