嗨,我已经待了两天了,没有得到任何解决方案或答案。它让我感到不安和沮丧。
我想做的是在我将POST提交到api服务器上的数据库后,更新子组件中的列表。子组件将打印数据库中所有记录的列表。当我提交时,孩子应该重新渲染该列表,列出数据库中的所有记录,包括刚提交的记录。 我必须点击页面刷新才能更新列表,包括新发布的记录。我不想刷新页面。只是列表(子)组件。
我尝试了Stackoverflow,Google等提供的所有可能解决方案。
我使用React 16.10。
请参阅下面的完整代码。告诉我要使其生效需要进行哪些更改。
我头疼。发布此问题后,我将获得泰诺醇。
我将从app.js开始:
import React, { Component } from 'react';
import { BrowserRouter as Router, Route } from "react-router-dom";
import './App.css';
import Navigation from './components/Navigation';
import TaskList from './components/tasklist';
import EditTask from './components/listEdit';
import CreateList from './components/listCreate';
class App extends Component {
render() {
return (
<Router>
<div>
<Navigation />
<div className="container">
<Route path="/" exact component={TaskList} />
<Route path="/edit/:id" component={EditTask} />
<Route path="/create" component={CreateList} />
</div>
</div>
</Router>
);
}
}
export default App;
listCreate.js(父组件)
import React, { Component } from 'react';
import TaskList from './tasklist';
import axios from 'axios';
export default class CreateList extends Component {
constructor(props) {
super(props);
this.onChangeListStatus = this.onChangeListStatus.bind(this);
this.onChangeListItem = this.onChangeListItem.bind(this);
this.onChangeListDue = this.onChangeListDue.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
list_status: '',
list_item: '',
list_due: '',
list_created: ''
}
}
onChangeListStatus(e) {
this.setState({
list_status: e.target.value
});
}
onChangeListItem(e) {
this.setState({
list_item: e.target.value
});
}
onChangeListDue(e) {
this.setState({
list_due: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
console.log(`Form submitted:`);
console.log(`Item Status: ${this.state.list_status}`);
console.log(`Item: ${this.state.list_item}`);
console.log(`Item Due: ${this.state.list_due}`);
const newItem = {
list_status: this.state.list_status,
list_item: this.state.list_item,
list_due: this.state.list_due,
};
axios.post('http://localhost:4000/lists/add', newItem)
.then(res => console.log(res.data));
this.setState({
list_status: '',
list_item: '',
list_due: '',
})
}
render() {
return (
<div>
<div style={{marginTop: 10}}>
<h3>Create New Item</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>New Item: </label>
<input type="text"
className="form-control"
value={this.state.list_item}
onChange={this.onChangeListItem}
/>
</div>
<div className="form-group">
<label>Due Date: </label>
<input
type="text"
className="form-control"
value={this.state.list_due}
onChange={this.onChangeListDue}
/>
</div>
<div className="form-group">
<label>Status: </label>
<input
type="text"
className="form-control"
value={this.state.list_status}
onChange={this.onChangeListStatus}
/>
</div>
<div className="form-group">
<input type="submit" value="Create Item" className="btn btn-primary" />
</div>
</form>
</div>
<TaskList reload={"true"}/>
</div>
)
}
}
tasklist.js(子级)
import React, { Component } from 'react';
import ItemRow from './itemRow';
import ItemField from './itemField';
import axios from 'axios';
export default class TaskList extends Component {
constructor(props) {
super(props);
this.state = { refreshlist: '',
lists: []
};
}
componentWillReceiveProps(nextProps) {
this.setState({ data: nextProps.data });
}
componentDidMount() {
axios.get('http://localhost:4000/lists/')
.then(response => {
this.setState({ lists: response.data });
})
.catch(function (error){
console.log(error);
})
}
// componentWillReceiveProps(props) {
// this.setState(this.state)
// }
static getDerivedStateFromProps(nextProps, prevState) {
if (nextProps.total !== prevState.total) {
return (this.setState({ refreshlist: nextProps.refreshlist })) // <- this is setState equivalent
}
// etc...
}
listoftask() {
return this.state.lists.map(function(currentItem, i){
return <ItemRow list={currentItem} key={i} />;
})
}
render() {
return (
<div>
<table className="table table-striped" style={{ marginTop: 20 }} >
<thead>
<ItemField />
</thead>
<tbody>
{ this.listoftask() }
</tbody>
</table>
</div>
)
}
}
更新: 这是我用来从db发送数据的api服务器
// const dotenv = require("dotenv");
import dotenv from 'dotenv';
import express from 'express';
import cors from 'cors';
// import uuidv4 from 'uuid/v4';
import mongoose from 'mongoose';
const app = express();
const listRoutes = express.Router();
dotenv.config();
const PORT = process.env.PORT || 4000;
const URI_lists = 'mongodb://localhost:27017/lists';
let List = require('./models/task');
app.use(cors());
app.use(express.json());
app.use(express.urlencoded({
extended: true
}));
mongoose.connect(URI_lists,
{useNewUrlParser: true,
useUnifiedTopology: true},
)
.then(() => {
console.log("MongoDB database initial connection established successfully.");
})
.catch((err) => {
console.log("ERROR! Could not connect to Database!");
console.log(err);
});
const connection = mongoose.connection;
connection.on('disconnected',()=> {console.log('lost connection!')});
connection.on('reconnected',()=> {console.log('reconnected to db again!')});
listRoutes.route('/').get(function(req, res) {
List.find(function(err, lists) {
if (err) {
console.log(err);
} else {
res.json(lists);
}
});
});
listRoutes.route('/:id').get(function(req, res) {
let id = req.params.id;
List.findById(id, function(err, list) {
res.json(list);
});
});
listRoutes.route('/update/:id').post(function(req, res) {
List.findById(req.params.id, function(err, list) {
if (!list)
res.status(404).send("data is not found");
else
list.list_item = req.body.list_item;
list.list_status = req.body.list_status;
list.list_due = req.body.list_due;
list.list_created = req.body.list_created;
list.save().then(list => {
res.json('List item updated!');
})
.catch(err => {
res.status(400).send("Update not possible");
});
});
});
listRoutes.route('/add').post(function(req, res) {
let newitem = new List(req.body);
newitem.save()
.then(list => {
res.status(200).json({'list': 'list item added successfully'});
})
.catch(err => {
res.status(400).send('adding new list item failed');
});
});
app.use('/lists', listRoutes);
app.listen( PORT, () => {
console.log('Server is running on Port: ' + PORT);
});
这是我在GitHub上的仓库:
(后端)https://github.com/zenkbaries/todoList (前端)https://github.com/zenkbaries/todolistapp
答案 0 :(得分:1)
将更新的道具传递给子组件时,子组件将重新渲染。否则它不需要更新。
查看您的配置,Child组件只有一个道具,并且永远不会改变。此外,您实际上只能从suffix = c("a","b")
中获取来自API的更新数据的时间,该时间仅在首次首次安装组件后触发。
为使功能正常运行,每次提交表单时都需要传递一个更新的道具。并在收到该更新后,向API提出新请求。
无需过多重构代码,我们可以执行以下操作:
在CreateList.js(父级)中:
componentDidMount()
因此,我们有一个newItem对象,该对象将传递给Child。我们只是使用它来识别更改。
taskList.js(孩子)
import React, { Component } from 'react';
import TaskList from './tasklist';
import axios from 'axios';
export default class CreateList extends Component {
constructor(props) {
super(props);
this.onChangeListStatus = this.onChangeListStatus.bind(this);
this.onChangeListItem = this.onChangeListItem.bind(this);
this.onChangeListDue = this.onChangeListDue.bind(this);
this.onSubmit = this.onSubmit.bind(this);
this.state = {
new_item: {},
list_status: '',
list_item: '',
list_due: '',
list_created: ''
}
}
onChangeListStatus(e) {
this.setState({
list_status: e.target.value
});
}
onChangeListItem(e) {
this.setState({
list_item: e.target.value
});
}
onChangeListDue(e) {
this.setState({
list_due: e.target.value
});
}
onSubmit(e) {
e.preventDefault();
console.log(`Form submitted:`);
console.log(`Item Status: ${this.state.list_status}`);
console.log(`Item: ${this.state.list_item}`);
console.log(`Item Due: ${this.state.list_due}`);
const newItem = {
list_status: this.state.list_status,
list_item: this.state.list_item,
list_due: this.state.list_due,
};
axios.post('http://localhost:4000/lists/add', newItem)
.then(res => {
this.setState({
list_status: '',
list_item: '',
list_due: '',
new_item: newItem
})
});
}
render() {
return (
<div>
<div style={{marginTop: 10}}>
<h3>Create New Item</h3>
<form onSubmit={this.onSubmit}>
<div className="form-group">
<label>New Item: </label>
<input type="text"
className="form-control"
value={this.state.list_item}
onChange={this.onChangeListItem}
/>
</div>
<div className="form-group">
<label>Due Date: </label>
<input
type="text"
className="form-control"
value={this.state.list_due}
onChange={this.onChangeListDue}
/>
</div>
<div className="form-group">
<label>Status: </label>
<input
type="text"
className="form-control"
value={this.state.list_status}
onChange={this.onChangeListStatus}
/>
</div>
<div className="form-group">
<input type="submit" value="Create Item" className="btn btn-primary" />
</div>
</form>
</div>
<TaskList newItem={this.state.new_item}/>
</div>
)
}
}
在子组件中,我们引入了import React, { Component } from 'react';
import ItemRow from './itemRow';
import ItemField from './itemField';
import axios from 'axios';
export default class TaskList extends Component {
constructor(props) {
super(props);
this.state = { refreshlist: '',
lists: []
};
}
componentDidMount() {
axios.get('http://localhost:4000/lists/')
.then(response => {
this.setState({ lists: response.data });
})
.catch(function (error){
console.log(error);
})
}
componentDidUpdate(prevProps){
if(prevProps.newItem !== this.props.newItem){
axios.get('http://localhost:4000/lists/')
.then(response => {
this.setState({ lists: response.data });
})
.catch(function (error){
console.log(error);
})
}
}
listoftask() {
return this.state.lists.map(function(currentItem, i){
return <ItemRow list={currentItem} key={i} />;
})
}
render() {
return (
<div>
<table className="table table-striped" style={{ marginTop: 20 }} >
<thead>
<ItemField />
</thead>
<tbody>
{ this.listoftask() }
</tbody>
</table>
</div>
)
}
}
钩子,该子钩子在子组件获得更新的道具或状态时触发。然后,我们只需重新应用与componentDidUpdate()
中相同的逻辑即可获取列表数据。