我怎样才能从数据库中得到正确的数据呢?

我使用nodejs + react + redux做了一个页面。 我在页面中做了一个编辑button,并想编辑我的数据。

现在我selectKUMAMOTO-CTI并将优先级从5更改为10.我使用ajax从数据库获取数据以填充空白。在提交之前,我可以从数据库中获得正确的数据。但是,当我改变优先级并单击编辑它填充的数据将是错误的,我必须刷新它,以获得正确的数据。

有时它会变成这样: 错误

有谁能告诉我如何解决?

这是pic: progress

这是我的代码。

server.js

const Koa = require('koa') const Router = require('koa-router') const cors = require('koa2-cors') const app = new Koa() const router = new Router() import { createStore } from 'redux' import { Provider } from 'react-redux' import serversReducer from '../client/reducers/reducer' import { renderToString } from 'react-dom/server' const store = createStore(serversReducer) const views = require('koa-views') const co = require('co') const convert = require('koa-convert') const json = require('koa-json') const onerror = require('koa-onerror') const bodyparser = require('koa-bodyparser') const logger = require('koa-logger') const debug = require('debug')('koa2:server') const path = require('path') //const ReactDOMServer = require('react-dom/server') const React = require('react') const config = require('./config') const routes = require('./routes') const mongoose = require('mongoose') const stateSchema = require('./models/State') const mission = require('./models/port') const port = process.env.PORT || config.port import Main from '../client/containers/Main' mongoose.connect('mongodb://127.0.0.1:27017/monitor', { useMongoClient: true }); mongoose.Promise = global.Promise; var State = mongoose.model("State", stateSchema); // error handler onerror(app) // middlewares app.use(bodyparser()) .use(json()) .use(logger()) .use(cors()) .use(require('koa-static')(__dirname + '/public')) .use(views(path.join(__dirname, '/views'), { options: { settings: { views: path.join(__dirname, 'views') } }, map: { 'ejs': 'ejs' }, extension: 'ejs' })) .use(router.routes()) .use(router.allowedMethods()) // logger app.use(async(ctx, next) => { const start = new Date() await next() const ms = new Date() - start console.log(`${ctx.method} ${ctx.url} - $ms`) }) router.get('/', async(ctx, next) => { const staticMarkup = await renderToString( <Provider store={store}> <Main /> </Provider> ) const preloadedState = store.getState(); //console.log(preloadedState); await ctx.render('index', { reduxData: preloadedState, helloComponentMarkup: staticMarkup }) }) router.post('/show', async(ctx, next) => { ctx.body = 'ok'; let newArray = []; await State.find({}, function(err, doc) { if (err) { return; } doc.forEach(function(element, index) { newArray.push(element); }) ctx.response.body = JSON.stringify(newArray); }).sort({ priority: 1 }) }) router.post('/edit', async(ctx, next) => { ctx.body = 'ok' await State.update({ _id: ctx.request.body.querymark }, { $set: { server_name: ctx.request.body.servername, jp_name: ctx.request.body.jpname, ip_address: ctx.request.body.ipaddress, port: ctx.request.body.port, priority: ctx.request.body.priority } }, function(err, doc) { if (err) { return; } }) }) router.post('/create', async(ctx, next) => { ctx.body = 'ok' await new State({ server_name: ctx.request.body.servername, jp_name: ctx.request.body.jpname, ip_address: ctx.request.body.ipaddress, port: ctx.request.body.port, priority: ctx.request.body.priority }).save(function(err) { if (err) console.log(err.toString()); }) }) router.post('/delete', async(ctx, next) => { ctx.body = 'ok' await State.remove({ _id: ctx.request.body.id }, function(err, doc) { if (err) { return; } }); }) routes(router) app.on('error', function(err, ctx) { console.log(err) logger.error('server error', err, ctx) }) module.exports = app.listen(config.port, () => { console.log(`Listening on http://localhost:${config.port}`) console.log(__dirname); }) 

ListContainer.js

 import React, { Component } from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' import { Router, Route, hashHistory } from 'react-router' import { Segment, Icon, Table, Modal, Button, Form } from 'semantic-ui-react' const axios = require('axios') class ListContainer extends Component { static propTypes = { test_data: PropTypes.object.isRequired, post_data: PropTypes.object.isRequired, onDeleteServer: PropTypes.func, onEditServer: PropTypes.func, initServers: PropTypes.func, index: PropTypes.number } constructor(props) { super(props) this.state = ({ servername: props.post_data.server_name, jpname: props.post_data.jp_name, ipaddress: props.post_data.ip_address, port: props.post_data.port, priority: props.post_data.priority }) } static defaultProps = { servers: [] } handleDeleteServer(index) { if (this.props.onDeleteServer) { this.props.onDeleteServer(this.props.index) } else { console.log("error") } } /*handleEditServer(index) { if (this.props.onEditServer) { this.props.onEditServer(this.props.index) } else { console.log("error") } this.setState({ open: false }) }*/ handleServerNameChange(event) { this.setState({ servername: event.target.value }) } handleJPNameChange(event) { this.setState({ jpname: event.target.value }) } handleIPChange(event) { this.setState({ ipaddress: event.target.value }) } handlePORTChange(event) { this.setState({ port: event.target.value }) } handlePriorityChange(event) { this.setState({ priority: event.target.value }) } handleSubmit(index) { axios.post('/edit', { querymark: this.props.post_data._id, servername: this.state.servername, jpname: this.state.jpname, ipaddress: this.state.ipaddress, port: this.state.port, priority: this.state.priority }).then((response) => { var new_data; if (response.data.success === false) { alert("error") } else { window.location.reload(); //console.log(this.props.post_data) dispatch(onEditServer(index, { querymark: this.props.post_data._id, servername: this.state.servername, jpname: this.state.jpname, ipaddress: this.state.ipaddress, port: this.state.port, priority: this.state.priority })) } }).catch(() => { }) this.setState({ open: false }) } state = { open: false } show = (size, dimmer) => () => this.setState({ size, dimmer, open: true }) close = () => this.setState({ open: false }) render() { const {open, size, dimmer} = this.state const post_data = this.props.post_data var updated_time = (new Date(post_data.updated_at)).toLocaleString().replace('/T/', '').replace('/\../+', '') var state_color = (post_data.state == "green") ? "green" : "red" var icon_name = (post_data.state == "green") ? "smile" : "warning sign" return ( <Table.Row> <Table.Cell><Icon name={icon_name} color={state_color}/></Table.Cell> <Table.Cell>{post_data.jp_name}</Table.Cell> <Table.Cell>{post_data.ip_address}</Table.Cell> <Table.Cell>{post_data.port}</Table.Cell> <Table.Cell>{updated_time}</Table.Cell> <Table.Cell>{post_data.priority}</Table.Cell> <Table.Cell> <div> <Icon link name='settings' color='purple' onClick={this.show('small', 'blurring')} /> <Modal size={size} dimmer={dimmer} open={open} onClose={this.close} closeIcon> <Modal.Header>Edit</Modal.Header> <Modal.Content> <Modal.Description> <Form> <Form.Group width='equal'> <Form.Field> <label>Server Name</label> <input value={this.state.servername} onChange={this.handleServerNameChange.bind(this)} /> </Form.Field> <Form.Field> <label>JP Name</label> <input value={this.state.jpname} onChange={this.handleJPNameChange.bind(this)} /> </Form.Field> </Form.Group> <Form.Group width='equal'> <Form.Field> <label>IP Address</label> <input value={this.state.ipaddress} onChange={this.handleIPChange.bind(this)} /> </Form.Field> <Form.Field> <label>Priority</label> <input value={this.state.priority} onChange={this.handlePriorityChange.bind(this)} /> </Form.Field> </Form.Group> <Form.Group> <Form.Field> <label>Port</label> <input value={this.state.port} onChange={this.handlePORTChange.bind(this)} /> </Form.Field> </Form.Group> </Form> </Modal.Description> </Modal.Content> <Modal.Actions> <Button color='black' onClick={this.close}> Nope </Button> <Button positive icon='checkmark' labelPosition='right' content="Submit" onClick={this.handleSubmit.bind(this)} /> </Modal.Actions> </Modal> </div> </Table.Cell> <Table.Cell><Icon link name='trash' color='purple' onClick={this.handleDeleteServer.bind(this)} /></Table.Cell> </Table.Row> ) } } const mapStateToProps = (state) => { return { servers: state.servers } } const mapDispatchToProps = (dispatch) => { return { onEditServer: (index, data) => { dispatch(editServer(index, data)) }, } } export default connect( mapStateToProps, mapDispatchToProps )(ListContainer) 

SegmentContainer.js

 import React, { Component } from 'react' import PropTypes from 'prop-types' import { connect } from 'react-redux' import { Container, Loader, Table, Grid, Icon, Button, Modal, Form } from 'semantic-ui-react' import SegmentList from '../components/SegmentContainer' import { initServers, deleteServer, editServer } from '../reducers/reducer' import MenuFix from '../components/Menu' const axios = require('axios') class SegmentContainer extends Component { static propTypes = { servers: PropTypes.array, initServers: PropTypes.func, onDeleteServer: PropTypes.func, onAddServer: PropTypes.func } constructor() { super() //this._loadData() this.state = { servername: '', jpname: '', ipaddress: '', priority: '' } } componentWillMount() { this._loadData() } componentDidMount() { if (this.timer) { clearInterval(this.timer) } this.timer = setInterval(() => { this._loadData() }, 3000) } componentWillUnmount() { clearInterval(this.timer) } _loadData() { let sorted_data = []; let posts_data = []; let response = axios.post('/show') .then((response) => { Object.keys(response.data).forEach(function(index) { sorted_data.push(response.data[index]); }) function _dataCompare(a, b) { if (a.priority > b.priority) return 1; if (a.priority < b.priority) return -1; return 0; } sorted_data.forEach((item, index) => { posts_data.push(item); }) posts_data.sort(_dataCompare); this.props.initServers(posts_data) //dispatch(initServers(posts_data)) }).catch(() => { }) } handleDeleteServer(index) { const {servers} = this.props axios.post('/delete', { id: servers[index]._id }).then((response) => { if (response.data.success === false) { alert("error"); } else { window.location.reload(); } }).catch(() => { }) if (this.props.onDeleteServer) { this.props.onDeleteServer(index) } } /*handleEditServer(index) { const {servers} = this.props axios.post('/edit', { querymark: this.props.servers._id, servername: this.state.servername, jpname: this.state.jpname, ipaddress: this.state.ipaddress, port: this.state.port, priority: this.state.priority }).then((response) => { if (response.data.success === false) { alert("error") } else { //window.location.reload(); dispatch(onEditServer(index, { querymark: this.props.servers._id, servername: this.state.servername, jpname: this.state.jpname, ipaddress: this.state.ipaddress, port: this.state.port, priority: this.state.priority })) } }).catch(() => { }) this.setState({ open: false }) }*/ handleCreate(server) { axios.post('/create', { servername: this.state.servername, jpname: this.state.jpname, ipaddress: this.state.ipaddress, port: this.state.port, priority: this.state.priority }).then((response) => { if (response.data.success === false) { alert("error"); } else { window.location.reload() dispatch(onAddServer(index, { servername: this.state.servername, jpname: this.state.jpname, ipaddress: this.state.ipaddress, port: this.state.port, priority: this.state.priority })) } }).catch(() => { }) this.setState({ open: false }) } handleServerNameChange(event) { this.setState({ servername: event.target.value }) } handleJPNameChange(event) { this.setState({ jpname: event.target.value }) } handleIPChange(event) { this.setState({ ipaddress: event.target.value }) } handlePORTChange(event) { this.setState({ port: event.target.value }) } handlePriorityChange(event) { this.setState({ priority: event.target.value }) } state = { open: false } show = (size, dimmer) => () => this.setState({ size, dimmer, open: true }) close = () => this.setState({ open: false }) render() { const {open, size, dimmer} = this.state return ( <Grid> <MenuFix /> <Container style = {{ marginTop: '6em' }}> <Table unstackable> <Table.Header> <Table.Row> <Table.HeaderCell colSpan='8'> <Button basic color='violet' floated='right' icon labelPosition='left' primary size='tiny' onClick={this.show('small', 'blurring')}> <Icon link color='violet' name='add' />Add </Button> <Modal size={size} dimmer={dimmer} open={open} onClose={this.close} closeIcon> <Modal.Header>Add</Modal.Header> <Modal.Content> <Modal.Description> <Form> <Form.Group width='equal'> <Form.Field> <label>Server Name</label> <input value={this.state.servername} onChange={this.handleServerNameChange.bind(this)} /> </Form.Field> <Form.Field> <label>JP Name</label> <input value={this.state.jpname} onChange={this.handleJPNameChange.bind(this)} /> </Form.Field> </Form.Group> <Form.Group width='equal'> <Form.Field> <label>IP Address</label> <input value={this.state.ipaddress} onChange={this.handleIPChange.bind(this)} /> </Form.Field> <Form.Field> <label>Priority</label> <input value={this.state.priority} onChange={this.handlePriorityChange.bind(this)} /> </Form.Field> </Form.Group> <Form.Group> <Form.Field> <label>Port</label> <input value={this.state.port} onChange={this.handlePORTChange.bind(this)} /> </Form.Field> </Form.Group> </Form> </Modal.Description> </Modal.Content> <Modal.Actions> <Button color='black' onClick={this.close}> Nope </Button> <Button positive icon='checkmark' labelPosition='right' content="Submit" onClick={this.handleCreate.bind(this)} /> </Modal.Actions> </Modal> </Table.HeaderCell> </Table.Row> <Table.Row> <Table.HeaderCell>State<Loader active inline size='small' /></Table.HeaderCell> <Table.HeaderCell>Server Name</Table.HeaderCell> <Table.HeaderCell>IP Address</Table.HeaderCell> <Table.HeaderCell>Port</Table.HeaderCell> <Table.HeaderCell>Updated</Table.HeaderCell> <Table.HeaderCell>Priority</Table.HeaderCell> <Table.HeaderCell>Edit</Table.HeaderCell> <Table.HeaderCell>Delete</Table.HeaderCell> </Table.Row> </Table.Header> <SegmentList posts_data = {this.props.servers} onDeleteServer={this.handleDeleteServer.bind(this)} /> </Table> </Container> </Grid> ) } } const mapStateToProps = (state) => { return { servers: state.servers } } const mapDispatchToProps = (dispatch) => { return { initServers: (servers) => { dispatch(initServers(servers)) }, onDeleteServer: (index) => { dispatch(deleteServer(index)) }, onEditServer: (index, data) => { dispatch(editServer(index, data)) }, onAddServer: (server) => { dispatch(addServer(server)) } } } export default connect( mapStateToProps, mapDispatchToProps )(SegmentContainer) 

reducer.js

 //action types const INIT_SERVERS = 'INIT_SERVERS' const ADD_SERVER = 'ADD_SERVER' const DELETE_SERVER = 'DELETE_SERVER' const EDIT_SERVER = 'EDIT_SERVER' //reducer export default function(state, action) { if (!state) { state = { servers: [] } } switch (action.type) { case INIT_SERVERS: return { servers: action.servers } case ADD_SERVER: return { servers: [...state.servers, action.server] } case EDIT_SERVER: return { servers: [...state.servers.slice(0, action.index), Object.assign({}, state.servers[action.index], { done: true }), ...state.servers.slice(action.index + 1)] /*servers: Object.assign([...state.servers], { [index]: action.data })*/ //servers: Object.assign({}, state[action.index], action.data) } case DELETE_SERVER: return { servers: [ ...state.servers.slice(0, action.index), ...state.servers.slice(action.index + 1) ] } default: return state } } // action creators export const initServers = (servers) => { return { type: INIT_SERVERS, servers } } export const addServer = (server) => { return { type: ADD_SERVER, server } } export const deleteServer = (index) => { return { type: DELETE_SERVER, index } } export const editServer = (index, data) => { return { type: EDIT_SERVER, index, data } } 

SegmentList.js

 import React, { Component, PropTypes } from 'react' import ListContainer from '../containers/ListContainer' export default class SegmentList extends Component { static propTypes = { posts_data: PropTypes.array, onDeleteServer: PropTypes.func, //onEditServer: PropTypes.func } static defaultProps = { posts_data: [] } handleDeleteServer(index) { if (this.props.onDeleteServer) { this.props.onDeleteServer(index) } } /*handleEditServer(index) { if (this.props.onEditServer) { this.props.onEditServer(index) } }*/ render() { return ( <div> {this.props.posts_data.map((data, i) => <ListContainer post_data={data} key={i} index={i} onDeleteServer={this.handleDeleteServer.bind(this)} /> )} </div> ) } } 

首先,反应是SPA,如果你使用重载只使用HTTP(无Ajax)来编辑。 这是SPA的解决scheme

在编码之前,主要的想法是在编辑之后更新你的数据,所以路线图应该是:

1.从服务器获取一个数组并存储到state.servers ,它应该是一个包含你的服务器信息的普通对象列表

2.更新时,您应该将更新应用到服务器,然后更新到本地存储,就像您在创build/删除时所做的一样,编辑最有可能与更多数据相同

那么你的handleSubmit应该是(从迭代通知索引作为参数)

 //index from iteration, should be passed from parent component handleSubmit(index) { const data = { querymark: this.props.post_data._id, servername: this.state.servername, jpname: this.state.jpname, ipaddress: this.state.ipaddress, port: this.state.port, priority: this.state.priority } axios.post('/edit', data).then((response) => { if (response.data.success === false) { alert("error"); } else { //window.location.reload(); dispatch(onEditServer(index,data)) } }).catch(() => {}) this.setState({ open: false }) }