简体   繁体   中英

React-router server-side rendering and ajax fetching data

I'm trying to implement react-router in my project and experiencing huge concept misunderstanding . For some of components in my app I need to fetch data from server. Previously I did it with this code:

$.get('/getSmData', options, function (result) {
      // set state with result or whatever
      }.bind(this));

placed in componentDidMount or in onClick functions but now, in order to make server routing, all requests go to my routing file.

How do I fetch data?

This is routing part of my server:

var  renderToString = require( 'react-dom/server').renderToString
var  match = require('react-router').match
var RouterContext  = require('react-router').RouterContext
var routes = require('./routes')

app.get('*', function (req, res) {

  match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
    if (error) {
      res.status(500).send(error.message)
    } else if (redirectLocation) {
      res.redirect(302, redirectLocation.pathname + redirectLocation.search)
    } else if (renderProps) {
        res.render('index', {
          react: renderToString(React.createElement(RouterContext, renderProps)),
          })
    } else {
      res.status(404).send('Not found')
    }
  })
})

This is routes.js

module.exports=  (
<Router history={browserHistory}>
      <Route path='/' component={index.App}>
          <Route path='/firstPage' component={First}>
            <Route path=':firstPageChild' component={FirstCh}/>
          </Route>
          </Route>
          <Route path='/secondPage' component={Second}/>
        </Route>
  </Router>

);

And let's say I need to fetch some data in child of one of children of firstPageChild in onButtonClick function. I can't prerender data and send with markup, so how should I do that?

I believe you have found the answer. But please let me answer, in case someone has the same problem (like I did, this morning).

  1. You should move the 404 error handling out of your "match react router" function,
  2. Add the third parameter "next" to the return function #1 above,
  3. Place your code to return AJAX data below this function.
  4. Create a route to handle the 404 not found error and place it on bottom.

So your code will be like this:

    app.get('*', function (req, res, next) {
       match({ routes, location: req.url }, (error, redirectLocation, renderProps) => {
          if (error) {
              res.status(500).send(error.message)
          } else if (redirectLocation) {
              res.redirect(302, redirectLocation.pathname + redirectLocation.search)
          } else if (renderProps) {
              res.render('index', {react: renderToString(React.createElement(RouterContext, renderProps)),
              })
          } else {
              // release control to the next middleware, in this case your URL for catching AJAX data
              next();
          }
       })
    })

    // return your AJAX data 
    app.get('/getSmData', function (req, res) {            
       res.send({ status: 'ok' });
    });

    // return 404 not found error 
    app.use(function (req, res) {            
       res.status(404).send('Not found');
    });

It seems i've figured it out. Apparently if app.get('*') stands after other requests it gonna catch only others and it totally makes sense.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM