Hacker News new | ask | show | jobs
by idbehold 3523 days ago
One thing that is never explained in these universal/isomorphic react frameworks/boilerplates is how to make a fetch() against your own server (e.g. a relative route). There's this https://zeit.co/blog/next#data-fetching-is-up-to-the-develop...

But what if my component looks like this:

  import React from 'react'
  export class exports React.Component {
    static async getInitialProps () {
      const res = await fetch('/api/user/123')
      const data = await res.json()
      return { username: data.profile.username }
    }
  }
6 comments

I like how react-server[0] deals with it; by having the `when` and `listen` callbacks expecting a promise, it becomes simple to `fetch()` any data you want server-side, including relative routes

[0] http://react-server.io/

is this your project or something? you seem to be name dropping it a few times in this thread.
Nope! It's just been an excellent tool that I'm a pretty big fan of, and relevant to a couple comments in this thread
Electrode.io is also new by WalmartLabs which I have not try yet.
Don't fetch within a component. Write a helper function: getUser(). It should decide which method to use to retrieve data.
How would it decide? What does the server-side version do since it won't have access to the req or res objects at this level of the code? If the /api/user/:id route is restricted based on the cookies that get sent, how/where do you validate that the user is allowed to get data from that route when rendering server-side?
That would be the responsibility of the route code, not the code doing the fetch().
Why would the route code need to know what data a deeply nested component needs? Making that the responsibility of the route code entirely defeats the purpose of an isomorphic/universal React application.
Yes, exactly! I've basically done only IT for the past 10 years and what little experience I have in web dev was with PHP in the good ol' days.

I want to get started with vue.js but there is NO mention of how to get data from a database. It is assumed the reader knows exactly what to do.

What you described is basically how I imagined it would work but I've just not been in this world for so long that I haven't been able to find the answer. (How to get data from a database with a system like vue.js.)

You're using the wrong tool for the job. Front-end JS frameworks do not mention how to get data from a database, because it's completely out of scope. Take a look at server frameworks/libraries like Rails, Phoenix, Express etc.
Will do thanks.
Super simple answer, so apologies if it sounds condescending or I've glossed over aspects entirely.

Libs like vue & react are essentially ui renderers, they create the html representation of app state, and handle all the DOM event binding and whatnot for you.

You will likely have some kind of client state management to take care of telling your ui to update, but essentially you will push json into that 'store' and that will then be used by your framework of choice to populate the page with content.

How that json gets there is largely upto you, and will be influenced by what you use to manage state, however you will need to handle getting data from the db server-side. Php or rails are popular, with reams of great (and some not so great) resources out there, but realistically you could use whatever you wanted.

Node.js is nice and could be useful if you want to focus on 1 language initially.

It wasn't condescending at all. On the contrary.

Partly I was tripped up because I have used Meteor and they handle everything for you. Before that I was using PHP and making SQL queries to MySQL directly.

In both of those cases I was able to get directly at the database. What you're saying is that I need a middle-tier that acts as the layer above the database but below the client (obviously.)

You mentioned Node.js. I know what that is and I know it's not a database. So it needs to connect to a database and then pass off data to the client. This is the piece of the puzzle I'm missing in my mental visualization.

I've learned that Laravel works well with Vue so I'll start there.

Thanks!

You can just wrap `fetch` with something that knows where your server is. In `Este.js` there's something like:

    function ensureServerUrl(url) {
      // parse and replace with your server url
      // in Este you read from a SERVER_URL environment variable
    }

    function fetch(url, options) {
      url = ensureServerUrl(url);
      return fetch(url, options);
    }
If the route requires a cookie to work how is that set when performing the fetch server-side?
Grab all the request cookies from the user and pass them along.
That sounds like a recipe for a confused deputy (https://en.wikipedia.org/wiki/Confused_deputy_problem).
All I know about confused deputy is from the Wikipedia article, but it seems like it wouldn't apply in this case. From Wikipedia: "The confused deputy problem occurs when the designation of an object is passed from one program to another, and the associated permission changes unintentionally, without any explicit action by either party. It is insidious because neither party did anything explicit to change the authority."

In the case the GP describes, the proxying web server has no additional authority on the API server: if the API route requires a cookie from the user, it doesn't matter whether that's passed directly or proxied.

That being said, feel free to correct me if I'm missing something. Also, thank you very much for giving me the name for this problem, it will come in very handy.

Inside the React component, (wherever this fetch() is being called from), where exactly are the user's cookies accessible from at this point in the code?
You can use a full URL? Also, typically you want to query a different API server. We query microservices, specifically.
I'd guess you need to use an absolute route (using a variable passed to the component props?). But yeah in practice you'd probably not want to slow down the rendering by doing an extra HTTP request so you'd probably send the data to the component in a more synchronous way.
> But yeah in practice you'd probably not want to slow down the rendering by doing an extra HTTP request so you'd probably send the data to the component in a more synchronous way.

How would you do that without breaking the whole universal/isomorphic aspect of this?

Check my demo using Redux: I populate the "initialState" on the server side [1] before React comes into the picture, and then populate it again on the client side [2], then client-side Redux can do its own thing.

Some explanation at [3] although that writeup (and this demo code) needs updating.

[1] https://github.com/firasd/react-server-tutorial/blob/master/...

[2] https://github.com/firasd/react-server-tutorial/blob/master/...

[3] https://medium.com/@firasd/quick-start-tutorial-universal-re...

But that means that I need to know which express routes are going to need what data. The react components should be able to declare the data they need and the server should be able to fetch that data before attempting to render server-side. There's not much of a point if I have to know ahead of time what data any react component rendered by a route will need.
I'm not sure 'components declaring the data they need' is a necessary React idiom especially if you're using Flux. But I do understand that any large application will need 'partial' state and you can't fill out the entire app data for every request like I do in my smaller demo apps.
You populate redux with all the data your app needs (if you're using setState to store state fetched from APIs on components, stop). Then you simply render your app in one go.
Okay, let's say I put the actual fetch() inside a redux "action creator" how am I fetching that data server-side? How does some arbitrary route know that a nested component needs to fetch() and then populate your store before rendering? And remember, the fetch() in the "action creator" is still trying to hit a relative route.
you call the action creator and dispatch its results to you redux store before rendering. For "arbitrary" routes, you design your application in a way that just by the pathname, query parameters, etc, you know exactly what data to get for the whole component tree. ..Don't use a relative route.
> For "arbitrary" routes, you design your application in a way that just by the pathname, query parameters, etc, you know exactly what data to get for the whole component tree.

That entirely defeats the purpose of an isomorphic/universal React application.