question-mark
Stuck on an issue?

Lightrun Answers was designed to reduce the constant googling that comes with debugging 3rd party libraries. It collects links to all the places you might be looking at while hunting down a tough bug.

And, if you’re still stuck at the end, we’re happy to hop on a call to see how we can help out.

Handle "asyncConnect" decorated containers that are hidden in the children components

See original GitHub issue

I have a nested structure of components (containers). Each has it’s own asyncConnect. The top one can hold up to N number of children. These children can come from a CMS. The schema is well defined and each maps to one of these children.

Let’s say the top level one would load available categories in an API call. Then the children ( sub-categories ) can be included dynamically, and each would worry about it’s own content, separately, independent of the top level container ( other than a route parameter that contains the id of the category ). Each of these children would load details for the sub-category it is responsible for.

Some pseudo code below:

<Route ... component={TopLevelContainer} />

@asyncConnect([{
  promise: ({ store: { dispatch, getState }, params: { categoryId } }) => {
    const promises = [];
    const state = getState();

    if (!categoryActions.isLoaded(state)) {
      promises.push(categoryActions.loadCategory(categoryId));
    }

    .... 
    return Promises.all(promises);
}])
export default class TopLevelContainer extends Component { ....
    someChildContext stuff ...
    ....
    render() {
        return (
            <div>
                <ChildContainer />
                <ChildContainer />
            </div>  
        );
    }
@asyncConnect([{
  promise: ({ store: { dispatch, getState }, params: { categoryId } }) => {
    const promises = [];
    const state = getState();

   // why is this code not running ? Am I forced to keep this on the parent? 

    // COMMENT BELOW
    if (!subCategoryActions.isLoaded(state, categoryId, 'someSubcategory')) {
      promises.push(subCategoryActions.loadCategory(categoryId, 'someSubcategory'));
    }

    .... 
    return Promises.all(promises);
}])
export default class ChildContainer extends Component { ....

So … I know it’s a bit of code, but I was using the repo that this was forked from in hopes that maybe this would work here. And yeah … am I doing something wrong? Is this a feature that’s implemented and support and I’m not doing something correctly? I also found this on the older repo but I’m not sure it’s what I need.

Also, regarding the // COMMENT BELOW part, is it somehow possible to get the context in the async connect? Or is that a more general thing?

Any help would be greatly appreciated, Thank you very much!

Issue Analytics

  • State:open
  • Created 7 years ago
  • Comments:23 (8 by maintainers)

github_iconTop GitHub Comments

9reactions
sergesemashkocommented, Aug 8, 2016

@oyeanuj, yes, I think I got pretty close, just would like to solve some obvious issues before submitting a PR.

3reactions
sergesemashkocommented, Aug 22, 2016

@oyeanuj, I’m trying to introduce as less breaking changes as possible. My current solution for server-side rendering has recursive call of renderToStaticMarkup() to handle sub-children asyncConnect decorators, like:

function loadOnServer(render, { store, filter = () => true, ...rest }) {
    const initialLoadState = store.getState().reduxAsyncConnect.loadState;
    const queue = [];
    // onResolve triggered on first unresolved deeply nested asyncConnect. 
    // If there are multiple asyncConnect on the same tree level queue will have multiple promises.
    renderToStaticMarkup(
      <Provider store={store} key="provider">
        <AsyncConnectResolver
          {...rest}
          filter={ filter }
          onResolve={(promise) => queue.push(promise)}
        >
          { render }
        </AsyncConnectResolver>
      </Provider>
    );

    return Promise.all(queue).then(results => {
      const loadState = store.getState().reduxAsyncConnect.loadState;
      // @TODO: Solution is taken from react-resolver, investigate better options. 
      // If load state hasn't change on last render that means there is no asyncConnect 
      // on deeply nested children left and we can leave the recursion.
      if (Object.keys(initialLoadState).length < Object.keys(loadState).length) {
        return loadOnServer(render, { store, filter, ...rest });
      }
      //@TODO: decide what to return here. Basically, reaching this point means all async connect are resolved;
      return {};  
    });
  }

Client-side solution is still in progress, but I’m trying out to have listener on each component wrapped by asyncConnect to handle its deeply nested children. So, let’s say we have:

<ReduxAsyncConnect>
  <AsyncConnectContainer>
    <AsyncConnectedChild>
      <AsyncConnectedSubChild />
    </AsyncConnectedChild>
  </AsyncConnectContainer>
  <SecondAsyncConnectContainer />
</ReduxAsyncConnect>

Resolving pipeline for given tree will be:

  1. ReduxAsyncConnect fires beginGlobalLoad() and listens for AsyncConnectContainer and SecondAsyncConnectContainer promises are resolved.
  2. AsyncConnectContainer is going to listen wether AsyncConnectedChild is resolved.
  3. AsyncConnectedChild is going to listen for AsyncConnectedSubChild and once AsyncConnectedSubChild is resolved, promise resolve is bubbling up to AsyncConnectedChild->AsyncConnectContainer->ReduxAsyncConnect
  4. Once two implicit children of ReduxAsyncConnect are resolved it fires endGlobalLoad()
Read more comments on GitHub >

github_iconTop Results From Across the Web

Support for nested components? · Issue #47 - GitHub
Handle "asyncConnect" decorated containers that are hidden in the children components makeomatic/redux-connect#45.
Read more >
React - Decorating Children and Handling Keys - Stack Overflow
In this code, I'm wanting to take each child and decorate it with some wrapping container or some behaviour. Forgetting for the moment...
Read more >
Show or hide children components in Angular 10
In this article, we will see how we can show or hide the child components in Angular. Lets start by creating a new...
Read more >
Call Methods on Child Components - Salesforce Developers
Note To communicate up the containment hierarchy, fire an event in a child component and handle it in an owner or container component....
Read more >
Testing Components with children - Testing Angular
Container Components have several types of dependencies. They depend on the nested child Components, but also Injectables.
Read more >

github_iconTop Related Medium Post

No results found

github_iconTop Related StackOverflow Question

No results found

github_iconTroubleshoot Live Code

Lightrun enables developers to add logs, metrics and snapshots to live code - no restarts or redeploys required.
Start Free

github_iconTop Related Reddit Thread

No results found

github_iconTop Related Hackernoon Post

No results found

github_iconTop Related Tweet

No results found

github_iconTop Related Dev.to Post

No results found

github_iconTop Related Hashnode Post

No results found