Skip to content
This repository has been archived by the owner on Jun 3, 2019. It is now read-only.

SSR & strategy for react-jobs nested in components #575

Open
oyeanuj opened this issue Mar 30, 2018 · 5 comments
Open

SSR & strategy for react-jobs nested in components #575

oyeanuj opened this issue Mar 30, 2018 · 5 comments

Comments

@oyeanuj
Copy link
Contributor

oyeanuj commented Mar 30, 2018

So, one of the problems while using this kit that I haven't been able to solve is being able to fetch data on server-side for more than one component in the tree. A typical case is with the following hierarchy:

<App>
 <JWTHandler> 
 { (isLoggedIn) => (
   <Switch>
    <Route>
      <ProfilePage />
    </Route>
   </Switch>
 )}
  </JWTHandler>
</App>

In this setup, the JWTHandler has to fetch some data (to validate the JWT token) using withJob, and the ProfilePage has to fetch profile data using withJob as well before the page is handed to the client.

But when I implement it like that, only the withJob from JWTHandler is run on the server and the one from ProfilePage is run on the client.

So, I am curious if this is possible using react-jobs, if folks have come across such a case in their usage, and what strategies have worked out for people?

cc: @ctrlplusb @birkir @strues or anyone else who has experience with this

@unleashit
Copy link

unleashit commented Mar 30, 2018

If it helps, I'm using withJob up to 3 levels deep without problem. I'm also using JWTs for auth, but doing things a bit differently than you not that it should have much bearing on your question (ex: I have public/private routes so I wrap my auth HOC around just the private routes... I also don't call the server from the Auth itself aside from checking for the token, and instead make all further secure requests get verified on the server. If any of them fail, the user won't see anything and will be immediately redirected to login).

@oyeanuj
Copy link
Contributor Author

oyeanuj commented Mar 30, 2018

@unleashit Thanks for sharing that. I am curious what your setup looks wrt the nesting. I ask since my observation is that only if children are available in the initial parse that their jobs are being respected. I wrote more on my observation this issue in react-jobs. Maybe you could also chime in on that?

@unleashit
Copy link

Hey @oyeanuj, I haven't had a chance to look into this deeply but I don't see why more than a first parse is necessary. I "would think" react-jobs + react-tree-walker would be able gather up all the promises before setting up a big "Promise.All" for everything found? I'm honestly not sure how it works under the hood though.

Unfortunately, I'd like to but I can't share the actual code with you because its under NDA for a client. But here's a stripped down example showing withJob in a parent/child combo which is working fine for me:

// I'm using withJob for the main App component, which holds the main Switch (meaning everything is a child of this)

export default withRouter(
  compose(
    connect(mapStateToProps, {
      logout,
      getData: getProductData,
    }),
    withJob({
      work: ({ productData, getData }) => {
        if (Object.keys(productData).length) {
          // product data cache hit;
          return productData;
        }
        return getData();
      },
      shouldWorkAgain: (prevProps, nextProps, jobStatus) =>
        Object.keys(prevProps.productData).length === 0,
      LoadingComponent: () => (
        <Spinner />
      ),
    }),
  )(App),
);

An example of a child route:

export default withRouter(
  compose(
    connect(mapStateToProps, {
      getOrders: getAllOrders,
      getOrdersCount: getAllOrdersCount,
    }),
    withJob({
      work: ({ getOrders, getOrdersCount }) =>
        getOrders()).then(() =>
          getOrdersCount(),
        ),
      LoadingComponent: () => <Spinner />,
    }),
  )(Admin),
);

I also have another withJob nested for each page of within the admin. It might help to say I'm not directly using the data returned from react-jobs in my render functions but instead using mapStateToProps to get it from the Redux store (I have actions/reducers doing that work).

So it's working and to me seems pretty straightforward. It just works(tm). If you're trying to do something different then this then I'm sorry I butt in.

@oyeanuj
Copy link
Contributor Author

oyeanuj commented Mar 31, 2018

@unleashit Thanks for sharing that! So it seems like what was really causing the issue was having nested react-jobs on components that are dynamically imported (which don't seem to resolve on server-side). Here is the ticket for that - ctrlplusb/react-tree-walker#27

@unleashit
Copy link

I'm also dynamically importing, but for whatever reason you might have to add a promise to get them to work together. See: ctrlplusb/react-jobs#51

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants