Receiving data before sending it to the server

I am discovering Este.js right now and I have a little problem with isomorphic applications. I don't understand how to make an api call prior to rendering the server side using renderToString ().

One solution is that all data is fetched at the router level using React Router. Depending on the top level route, I can predict what data will be needed, make an api call, and then call React.renderToString.

Great, but I still have to declare data dependencies at the component level and at the router level. I end up writing the same code twice and I don't believe this is the best way to do it.

EDIT: Ok, now I can do what I want. Using React-Router and link I was able to do the following:

By providing this global application state, I want to preselect todos when specifying / todos

initialstate.js

{
  auth: {
    data: null,
    form: null
  },
  examples: {
    editable: {
      state: null,
      text: 'Some inline-editable text.'
    }
  },
  i18n: {
    formats: {},
    locales: initialLocale,
    messages: messages[initialLocale]
  },
  pendingActions: {},
  todos: {
    editables: {},
    newTodo: {
      title: ''
    },
    list: [{
      id: 1,
      title: 'first todo yipiyo'
    }]
  },
  users: {
    viewer: null
  }
}

      

todos.react.js

In the todo component, I declare a static function fetchData. Since I want to get the correct key in my appState, I pass "list" as a parameter. Feels dirty.

class Todos extends Component {

  static fetchData(){
    return actions.loadAllTodos('list');
  }

  componentDidMount(){
    Todos.fetchData();
  }

  render() {
    ...
  }

}

      

actions.js

Api call and stuff, I pass the key to the promise - Feels hackish

export function loadAllTodos(key) {

  const promise = new Promise((resolve, reject) => {

    Api.get()
    .then(res => {
      res.key = key; //hacky time
      resolve(res)
    })
    .catch(err => {
      reject(err);
    })

  });

  return dispatch(loadAllTodos, promise);

}

      

render.js

router.run((Handler, routerState) => {

  var promise = Promise.all(routerState.routes
        .filter(route => route.handler.fetchData)
        .map(route => {
          return route.handler.fetchData();
        })
      );

  promise.then(resp => {

    console.log(resp);

    //Displays : 
    [ { id: 2, title: 'Im a second todo' },{ id: 3, title: 'I like todo' },
    cursor: 'list' ]

    //Some stuff to add resp to appState, using the correct key, yey iso+api=win
    appState = mergeThisWithMagic(appState, resp);

    const html = preloadAppStateThenRenderHtml(Handler, appState);
    const notFound = routerState.routes.some(route => route.name ===
      'not-found');
    const status = notFound ? 404 : 200;
    res.status(status).send(html);
    resolve();

  });


});

      

As you can see, I will create a function to update appState with updated todoList.

Can all this be done? I would like to get some feedback because I feel like I am walking the dark path: (.

+3


source to share


1 answer


I have accomplished this in my isomorphic server side application by putting fetchData functions in the statics

component (s) object and using promises that wait until all data is returned before the application is shown in line.



Then you will pass the returned data to the processed component via props. This example was instrumental in my development of this application. React Mega Demo .

+2


source







All Articles