markdalgleish / redial

Universal data fetching and route lifecycle management for React etc.
1.1k stars 42 forks source link

Fetch data when deep linking to sub route doesn't work #47

Open adriaanbalt opened 7 years ago

adriaanbalt commented 7 years ago

It appears that the following snippet causes sub routes to never perform their fetch if you deep link directly to them.

// Don't fetch data for initial route, server has already done the work:
      if (window.INITIAL_STATE) {
        // Delete initial data so that subsequent data fetches can occur:
        delete window.INITIAL_STATE
      } else {
        // Fetch mandatory data dependencies for 2nd route change onwards:
        trigger('fetch', components, locals)
      }

What if you are rendering a page that is partially server rendered but still needs to retrieve more data? For example, I load up my profile page directly instead of going to the home page first?

The above code works when going from the first page to the second page. But regardless will never fetch on the first page.

If this is intentional, can you explain why?

davidfurlong commented 7 years ago

I'm not sure I understand the question correctly @adriaanbalt , but react-router's match callback provides an object renderProps. However this renderProps object has a property components that only provides the top level components for the current Route, and their props. This is how redial triggers hooks - a lookup in this list of component. This makes it impossible for redial to trigger in deeply nested components (relative to the nearest react-router Route parent) See below the trigger source

export default (name, components, locals) => {
  const promises = (Array.isArray(components) ? components : [components])

    // Filter out falsy components
    .filter(component => component)

    // Get component lifecycle hooks
    .map(component => ({ component, hooks: component[propName] }))

    // Filter out components that haven't been decorated
    .filter(({ hooks }) => hooks)

    // Calculate locals if required, execute hooks and store promises
    .map(({ component, hooks }) => {
      const hook = hooks[name];

      if (typeof hook !== 'function') {
        return;
      }

      try {
        return typeof locals === 'function' ?
          hook(locals(component)) :
          hook(locals);
      } catch (err) {
        return Promise.reject(err);
      }
    });

  return Promise.all(promises);
};