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

SSR: Transition renders nothing via renderToString #435

Closed
fnpen opened this issue Jan 11, 2019 · 17 comments
Closed

SSR: Transition renders nothing via renderToString #435

fnpen opened this issue Jan 11, 2019 · 17 comments

Comments

@fnpen
Copy link

@fnpen fnpen commented Jan 11, 2019

I run this code via babel-node.

const html = renderToString(
      <>
        <Transition
          items={true}
          initial
          //initial={{ opacity: 1 }}
          from={{ opacity: 0 }}
          enter={{ opacity: 1 }}
          leave={{ opacity: 0 }}
        >
          {show =>
            show && (props => <div style={props}>✌️</div>)
          }
        </Transition>
      </>
    );

And console output nothing!

If I do window !== undefined HOC, I have React.hydrate warnings, because structure is not valid.

How I can use it?

This is simple example, if I use it with react-router, can't show full page.
I want use one library. With react-pose everything is ok.


I tryed debug it an in Keyframes.js:
if (!props || Object.keys(props).length === 0) return null
if I comment this line, code appears after renderToString, but still react-router not show the page.

How solve this problem?

Now this is unusable with SSR apps.

@drcmda

This comment has been minimized.

Copy link
Collaborator

@drcmda drcmda commented Jan 11, 2019

There was a topic about this here before. Transition bases on Keyframes and Keyframes is async. It doesn't have a way to fetch props until next render (due to async functions and promises). With hooks i can fix this, with render props it's going to get tough. Someone's made a SSR ready fork somewhere, with some hack that fixes this in some cases. But i would wait ... this will all get easier.

@fnpen

This comment has been minimized.

Copy link
Author

@fnpen fnpen commented Jan 12, 2019

Hooks is not solution for all situations, need update docs, that SSR is completely unsupported.
Because it's important reason do not spend time with this library and select other one. :-(

I think possible check SSR render inside Keyframes and run async code.

@drcmda

This comment has been minimized.

Copy link
Collaborator

@drcmda drcmda commented Jan 12, 2019

In the other thread people have found solutions, i know it's running on both gatsby and next for instance.

#278

But this stuff is tricky because SSR is purely linear whereas animations are not. With classes it gets worse because in React they have changed when updates occur, you do this after the component has rendered in componentDidUpdate now (previously componentWillUpdate). And still worse, keyframes are async by nature, that's just what they do, the allow you to script animations with promises. I'm not against trying to fix it, but it needs community support, PR's, more discussion.

Hooks on the other hand take some of the burden away, because they are linear, one thing leads to another. That gives you more control over what's happening. I plan focussing on hooks as the primary means to drive animation in 8.x, i will consider the render props based api legacy by then.

@fnpen

This comment has been minimized.

Copy link
Author

@fnpen fnpen commented Jan 13, 2019

I think #278 is different issue. I do not have errors, my html code is empty without any error. And I do not need animation, I need blank html code and after hydration, lib can start its async work.

@GriffinSauce

This comment has been minimized.

Copy link

@GriffinSauce GriffinSauce commented Jan 15, 2019

I agree, when doing SSR you don't need animation on the server side, just a static initial situation, which is either the "enter" or "from" state.

I expected initial to be used when animation is not possible.

<Transition
  items={comments}
  keys={comment => comment._id}
  initial={{ opacity: 1 }}
  from={{ opacity: 0 }}
  enter={{ opacity: 1 }}
  leave={{ opacity: 0 }}
>
  {comment => style => (
    <div style={style} key={comment._id}>
      <CommentThread
        comment={comment}
      />
    </div>
  )}
</Transition>

^ so here I would expect my comments to be rendered with opacity: 1 on the server. Instead they are not rendered on the server at all and only rendered on the client with opacity: 1


Another option is to give the consumer control by exposing a prop to manually force "dumb" rendering. All SSR solutions have a way to know whether you're currently in a server or browser so you could dictate a specific output:

<Transition
  items={comments}
  keys={comment => comment._id}
  initial={{ opacity: 1 }}
  force={!process.env.BROWSER ? { opacity: 1 } : null}
  from={{ opacity: 0 }}
  enter={{ opacity: 1 }}
  leave={{ opacity: 0 }}
>
  {comment => style => (
    <div style={style} key={comment._id}>
      <CommentThread
        comment={comment}
      />
    </div>
  )}
</Transition>

^ if force has a value, don't animate but just render with those props
if null, ignore and try to animate.

Does this make sense as a solution?

@GriffinSauce

This comment has been minimized.

Copy link

@GriffinSauce GriffinSauce commented Jan 15, 2019

@fnpen maybe this helps you, I managed to work around this issue by switching out the Transition altogether: https://gist.github.com/GriffinSauce/f626a1b40826d3b6b1d73206f90a0db7

@CosmaTrix

This comment has been minimized.

Copy link

@CosmaTrix CosmaTrix commented Jan 17, 2019

Hi all,

There was already a discussion going regarding this at issue #322. That's the one @drcmda was referring to.

@fnpen Check my fork out in the comments. I agree with you that there should be a fix and that hooks are not always the solution (for now).

@drcmda I think we should go back to issue #322 and see what can be done. The forked solution feels stable, but I'd like to hear from somebody in the core team. Maybe we should plan some sort of call and find a solution together. I'm willing to help because the SSR rendering issue is stopping me for using react-spring for some projects. 😢

@GriffinSauce I like your solution and I've tried that out myself some time ago. But that's still a workaround.

@GriffinSauce

This comment has been minimized.

Copy link

@GriffinSauce GriffinSauce commented Jan 18, 2019

Agreed, thanks for linking that issue!

@drcmda

This comment has been minimized.

Copy link
Collaborator

@drcmda drcmda commented Jan 23, 2019

@CosmaTrix in the 8.x hooks version it is fixed, because it extracts "from" and renders right away. Would this be a way for render props as well?

@fnpen

This comment has been minimized.

Copy link
Author

@fnpen fnpen commented Jan 23, 2019

@drcmda better fix in current version also,
or do you think make the library 'hooks only'?

@LekoArts

This comment has been minimized.

Copy link

@LekoArts LekoArts commented Feb 1, 2019

I currently use Transition for my page transitions on a Gatsby starter but it seems that react spring is totally removing the SSR: https://github.com/LekoArts/gatsby-starter-portfolio-emilia/issues/6

I also reported this here: #322 (comment)

The index.html doesn't contain anything
image

@drcmda

This comment has been minimized.

Copy link
Collaborator

@drcmda drcmda commented Feb 2, 2019

@fnpen no, it won't be hooks only, though in some cases it will probably be harder to backport fixes since the renderprops version is a little bit more complex.

@drcmda

This comment has been minimized.

Copy link
Collaborator

@drcmda drcmda commented Feb 2, 2019

@LekoArts could you explain more ... what do you mean with it removes ssr?

@LekoArts

This comment has been minimized.

Copy link

@LekoArts LekoArts commented Feb 2, 2019

Sorry, I should have been more clear.

So Gatsby has these two files, gatsby-browser and gatsby-ssr. The former gets run when the site is rehydrated into the React app, the latter when the build is happening.

I had wrapped my entire Gatsby app in gatsby-ssr with the Transition component (for page transitions). Gatsby couldn't get "through" the Transition and build out it's usual HTML structure hence my index.html file was completely empty - and therefore broke SSR (for Gatsby).

The solution to the problem was to replace/remove the Transition component from Gatsby's SSR part (in gatsby-ssr) since the Transition component doesn't add any markup but only does CSS styles to the div. So for the initial SSR build I just could use a div instead of the Transition component.

@fnpen

This comment has been minimized.

Copy link
Author

@fnpen fnpen commented Feb 3, 2019

@drcmda you need to add notice and module is not compatible with SSR, and people need to select another one.

@aleclarson

This comment has been minimized.

Copy link
Member

@aleclarson aleclarson commented May 27, 2019

Can someone see if this is fixed in react-spring@next? Closing for now.

@aleclarson aleclarson closed this May 27, 2019
@aleclarson aleclarson added the SSR label May 27, 2019
@tim-soft

This comment has been minimized.

Copy link

@tim-soft tim-soft commented Jun 16, 2019

@aleclarson just tested a NextJS site and the inner HTML does seem to render out properly on v9 beta 21 with <Transition />

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
7 participants
You can’t perform that action at this time.