这是我写的一个监控系统,使用了react redux nodejs,按照数据库的priority排序,使用编辑功能时,可以正常编辑,显示也是正确的,但是第一次编辑之后再对同意条目编辑,发现在不刷新的情况下,ajax获取的数据是不争取的,指向的是重新排序前的那个数据,刷新之后又正常了,请问我该怎么解决这个问题。
这里用图片展示了过程:
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 { Segment, Icon, Table, Modal, Button, Form } from 'semantic-ui-react'
const axios = require('axios')
export default class ListContainer extends Component {
static propTypes = {
post_data: PropTypes.object.isRequired,
onDeleteServer: 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
})
}
handleDeleteServer() {
if (this.props.onDeleteServer) {
this.props.onDeleteServer(this.props.index)
}
}
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() {
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) => {
if (response.data.success === false) {
alert("error");
} else {
window.location.reload();
}
}).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>
)
}
}
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,
}
constructor() {
super()
this._loadData()
/*this.state = {
servername: '',
jpname: '',
ipaddress: '',
priority: ''
}*/
}
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)
}).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)
}
}
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();
}
}).catch(() => {
})
this.setState({
open: false
})
if (this.props.onAddServer) {
this.props.onAddServer(server)
}
}
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: (serverIndex) => {
dispatch(deleteServer(serverIndex))
},
onEditServer: (serverIndex) => {
dispatch(editServer(serverIndex))
},
onAddServer: (server) => {
dispatch(addServer(server))
}
}
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(SegmentContainer)