Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Share a component between queries but load different component containers #139

Closed
paulcredmond opened this issue Jan 11, 2018 · 9 comments
Closed

Comments

@paulcredmond
Copy link

paulcredmond commented Jan 11, 2018

Say you have a form component called <SignUpForm /> and you want it wrapped in different components for mobile and desktop - <Mobile /> which provides a swiping experience and <Desktop /> which is a normal form layout.

export class App extends React.Component {
  render() {
    return (
    <section>
      <MediaQuery maxWidth={767} component={Mobile}>
        <SignUpForm />
      </MediaQuery>
      <MediaQuery minWidth={768} component={Desktop}>
        <SignUpForm />
      </MediaQuery>        
    </section>
    );
  }
}

I thought I could use the load component feature to use these wrappers... the above does work in terms of loading the form in the right containers, but any field data filled out in one is lost when resizing the browser as it's loading a new instance of the component. Can I prevent this from happening?

@yocontra
Copy link
Owner

yocontra commented Jan 11, 2018

Ternary:

<MediaQuery maxWidth={767} component={Mobile}>
  {(matches) => matches ? <SignUpMobile /> : <SignUpDesktop />}
</MediaQuery>

Property:

<MediaQuery maxWidth={767} component={Mobile}>
  {(matches) => <SignUp mobile={matches} />}
</MediaQuery>

Put a key on the child to keep it from rendering a new one if you don't want that behavior.

@paulcredmond
Copy link
Author

Thanks for the reply. Only the wrapper component is different, not the <SignUpForm /> I used in the example above. I tried your example but the same thing happens... <SignUpForm /> re-renders when changing breakpoint. How can I use keys to stop that happening?

@yocontra
Copy link
Owner

@paulcredmond https://stackoverflow.com/ for questions like this, github issues is for bug reports only.

@jannisg
Copy link

jannisg commented Nov 14, 2018

Sorry for the reply to an old, closed, issue but I have been banging my head against this same issue too and after hours trying to figure this out cannot seem to implement either of your suggested options @contra.

I've tried:

  • Explicit key=""
  • Ternary (with and without key="")

A super simplified test case is available here inside the LayoutManager.jsx file: https://codesandbox.io/s/oq487n1j9

@paulcredmond did you ever figure this out?

@yocontra
Copy link
Owner

@jannisg What's the bug? I resize the viewport and the header shows up/disappears as intended in the code.

@jannisg
Copy link

jannisg commented Nov 15, 2018

@contra Thanks for even looking at this :)

The issue is that the contained form (the child being passed into the <MediaQuery> is unmounting/mounting as I resize and hit the breakpoints which cause the form values (if you enter one, then resize) to be lost.

I cannot figure out how to make the instance of <MyForm /> that is the child of <LayoutManager> in the index.js "persist" when wrapped with the MediaQuery which causes the unmount/mount cycle of MyForm.

For what it's worth, I don't see this as a bug in this module. I just piggybacked on this closed thread as it's the same issue that @paulcredmond was trying to solve and my other StackOverflow research and experimentation in the CodeSandbox that I linked didn't yield any solutions.


Update: The only way I have been able to get this to work is by wrapping all individual children that should be conditionally shown/hidden in individual conditionals based on the isMatch flag: https://codesandbox.io/s/q8q72wn279

Still, it would be nice if there was a way to simply approach it from a "children" of the container perspective and return entire layouts with the children being injected in certain places as per my first non-working example.

@yocontra
Copy link
Owner

@jannisg I think your issue is that react is seeing the component at different depths in the virtual DOM and treating it as a fresh component. I'm not sure if there's anything you can do to fix that since it's react core behavior, and it seems like a fine design choice on their part. It's going to seem pretty bootleg but you could always display: isMatch ? undefined : 'none' on the nav + asides.

These should provide some more insight:

@jannisg
Copy link

jannisg commented Nov 15, 2018

Many thanks @contra, really enjoyed reading those links on the topic. ❤️

@paulcredmond

This comment has been minimized.

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

No branches or pull requests

3 participants