React + Express - 获取新数据时刷新页面

时间:2017-04-10 16:14:15

标签: reactjs express post

当我在服务器上收到带有数据的POST请求时,我想在客户端刷新信息。

目前它看起来像这样。我在服务器端有POST请求:

final AuditReader auditReader = AuditReaderFactory.get( session );
List results = auditReader.createQuery()
  .forRevisionsOfEntity( Periodicity.class, true, false )
  // add the revision number predicate
  .add( AuditEntity.revisionNumber().eq( revisionId ) )
  // add the instrument predicate
  .add( AuditEntity.property( "id.instrumentId" ).eq( instrumentId ) )
  .getResultList();

当我成功插入数据库时​​,我想自动刷新客户端。要显示来自标记的信息'来自数据库的JSON我正在使用MarkersList组件和MarkerPage组件:

MarkersList.js

 app.post('/login',jsonParser,  function (req, res) {
  if (!req.body) return res.sendStatus(400);
  if(req.body){
    console.log(req.body);
    mongodb.connect(dbUrl,function(err,db){
      db.collection('markers').insertOne(req.body);
    });
    return res.sendStatus(200);
  }
})

MarkerPage.js

 export default function MarkersList({markers})  {
  const emptyMessage=(
    <p> There are no coordinates to display </p>
  );

  const markersList=(
    <div>{markers.map(marker=> <p>{marker.title}</p>)}</div>
  );

  return(
    <div>
      {markers.length === 0 ? emptyMessage:markersList}
    </div>
  );
}

MarkersList.propTypes={
  markers:React.PropTypes.array.isRequired
}

actions.js

import React from 'react';
import MarkersList from './MarkersList';
import {connect} from 'react-redux';
import {fetchMarkers} from './actions';

class Markers extends React.Component{
  componentDidMount(){
    this.props.fetchMarkers();
  }

  render(){
    return(
      <div>
        <p>LISTA</p>
        <MarkersList markers={this.props.markers}/>
      </div>
    )
  }
}


Markers.propTypes={
  markers: React.PropTypes.array.isRequired,
  fetchMarkers: React.PropTypes.func.isRequired
}

function mapStateToProps(state){
  return{
    markers:state.markers
  }
}

export default connect(mapStateToProps,{fetchMarkers})(Markers);

index.js -client side:

export const SET_MARKERS='SET_MARKERS';

export function setMarkers(markers){
  return{
    type:SET_MARKERS,
    markers
  }
}

export function fetchMarkers(){
  return dispatch => {
    fetch('/api/markers')
      .then(res=>res.json())
      .then(data=>dispatch(setMarkers(data.markers)));
    ;
  }
}

如何从服务器端发出类似动作的内容,以便在客户端显示数据库的当前状态?

1 个答案:

答案 0 :(得分:1)

您可以通过多种方式执行服务器端驱动的客户端更新:

客户端超时或轮询请求

非常不满意,因为它要求您预测服务器端代码的执行时间,并且它实际上并不是由服务器驱动的。 以下是执行此类思考的两种解决方案:

在带有mixin

的MarkerPage组件中

使用像react-timer-mixin之类的mixin每隔X秒在MarkerPage组件中调用this.props.fetchMarkers(在下面的示例中为2秒)。

import React from 'react';
import TimerMixin from 'react-timer-mixin'; 
import MarkersList from './MarkersList';
import {connect} from 'react-redux';
import {fetchMarkers} from './actions';

class Markers extends React.Component{
 componentDidMount(){
    this.props.fetchMarkers();
      TimerMixin.setTimeout(() => { 
       this.props.fetchMarkers();
      },2000);
  }

  render(){
    return(
      <div>
        <p>LISTA</p>
        <MarkersList markers={this.props.markers}/>
      </div>
    )
  }
}


Markers.propTypes={
  markers: React.PropTypes.array.isRequired,
  fetchMarkers: React.PropTypes.func.isRequired
}

function mapStateToProps(state){
  return{
    markers:state.markers
  }
}

export default connect(mapStateToProps,{fetchMarkers})(Markers);

为了避免混淆,它会向你保证定时器会被组件破坏。

在我看来,确保数据重新加载并不是组件的目的。它的唯一目的是显示。

在中间件或外部模块中。

为了避免从组件重新加载数据,我更喜欢使用将分派给商店的独立代码。它不会干扰组件代码。 以下是根据我的申请改编的一个例子:

index.js -client side:

import {fetchMarkers} from './actions';

function startAutoReloadMarkers(store) {
  window.setInterval(() => {
    store.dispatch(fetchMarkers());
  }, 2000);
}

const store= createStore(
  rootReducer,
  composeWithDevTools(
    applyMiddleware(thunk)
  )
)

startAutoReloadMarkers(store)

第二种解决方案。使用套接字并处于真正的实时环境中。

这是从反应/减少优势中获利的一种非常好的方式。 这是我在我的应用程序中使用的解决方案:

在服务器端登录代码中:

// On user login (using a websocket), I trigger a call to an external service wich will respond later (my seneca service is the equivalent of your mongodb insert)
seneca().use(senecaTransactions).act({ cmd: handleAutomaticOperations, userId: user._id }, (error, transactions) => {
  if(error) {
    // You don't need thios
    reject(error);
  } else {
    // You don't need this
    resolve(true);
    // Here I will notify the client that some transactions have been updated/added
    socket.emit(TRANSACTION_UPDATED, transactions);
  }
});

index.js -client side:

import Socket from '../Socket';
import { TRANSACTION_UPDATED } from '../constants/SocketActions';

export function startTransactionsMiddleware(store) {
  Socket.on(TRANSACTION_UPDATED, (transaction) => {
    // The equivalent of your dispatch(fetchMarkers()
    store.dispatch(transactionUpdated(transaction));
  });      
}

// Same think that the previous example
startTransactionsMiddleware(store);

This way once the TRANSACTION_UPDATED is trigerred in the server my display will be updated thanks to redux.

如果您需要一些帮助来实施第二个解决方案,请不要犹豫。