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

Rendering within an iframe from outside the iframe #130

Open
lencioni opened this issue Aug 26, 2016 · 11 comments
Open

Rendering within an iframe from outside the iframe #130

lencioni opened this issue Aug 26, 2016 · 11 comments

Comments

@lencioni
Copy link
Collaborator

I have recently run into an issue when rendering some React components that use Aphrodite in an iframe. Specifically, when the the JavaScript that renders the components is running in the iframe's parent context. The component is rendered correctly with the Aphrodite className, but the styles are added to the head of the parent document instead of the iframe document.

I've hacked around this by finding the aphrodite styles via document.querySelector('style[data-aphrodite]') and copying them into the iframe.

Do you see a reasonable way to make this just work without having to worry about it?

@lencioni lencioni changed the title Rendering within an iframe Rendering within an iframe from outside the iframe Aug 26, 2016
@xymostech
Copy link
Contributor

Huh. Interesting problem! How are you rendering the react components? Can you pass the actual React components between the frames, or do you generate HTML (e.g. with ReactDOMServer.renderToString) and pass that?

@Jujhaar
Copy link

Jujhaar commented Aug 27, 2016

It's a bit of a roundabout way - we render the iframe with html elements with specific class names, and then replace those elements in the iframe with React elements. Does that answer your question?

@sophiebits
Copy link

sophiebits commented Aug 27, 2016

React DOM does (mostly) support rendering into a container in another window.

@lencioni
Copy link
Collaborator Author

I don't have the code in front of me right now, but IIRC, it was something along the lines of this (simplified):

<html>
  <head>
    <script src="my-app.js"></script>
  </head>
  <body>
    <iframe id="my-iframe">
      <div id="react-thing"></div>
    </iframe>
  </body>
</html>

The JS in my-app.js renders React into the react-thing div which is inside of the iframe. Since the JS is executed in the context of the parent document, and Aphrodite puts the styles in the head of document, the styles end up not styling the rendered components.

@xymostech
Copy link
Contributor

Interesting! I didn't know that React supported that. Unfortunately, there's no way for Aphrodite to know implicitly which frame you are trying to render to, because it isn't connected to React. Maybe we could expose an API like StyleSheet.renderInFrame(frame, () => { ... }) and then it would put the styles in that given frame?

@lnmunhoz
Copy link

@lencioni I am facing the same issue working with iframe, but in my case, sometimes the style tag is not appended at all. I don't now what is happening... Depending on the screen, the style is not appended andI even if I change "views", doesn't get new css from components.

@lnmunhoz
Copy link

lnmunhoz commented Oct 27, 2016

I am debugging inject.js and seems that this line inject.js#168 is causing my bug. Its sending a empty string to injectStyle method and its not injecting anything. If I remove this line, it works just fine.

@xymostech
Copy link
Contributor

@lnmunhoz Can you provide a more complete example of what you're trying to do? I seriously doubt that removing that line is the solution to your problem.

@lnmunhoz
Copy link

lnmunhoz commented Oct 27, 2016

Hi @xymostech, I am rendering an App inside a iframe. What basically happens is when the page loads, aphrodite randomically don't append the <style> tag inside the iframe (neither outside, on the host website). Its a very strange behaviour and I can't figure out why this is happening.

I use react-storybook to manage my components and all of them are rendering fine and the <styles> tag is being appended on the <head>, but when I use them in the iframe, sometimes the styles are applied and other times not. The only way that makes 100% guarantee to append is removing that line but I know is not the right solution.

The App stack that runs inside the iframe is:

I don't know if it helps, but I am looking for help to figure out what is going on.

This is one of the components, I am doing something wrong to bug aphrodite?

import React, { PropTypes } from 'react';
import { StyleSheet, css } from 'aphrodite';

const styles = StyleSheet.create({
  root: {
    borderRadius: '4px',
    border: 'none',
    color: 'white',
    backgroundColor: '#1088cc',
    boxShadow: '0px 2px 0px 0px #005888',
    fontSize: '15px',
    letterSpacing: '0.02em',
    padding: '10px 20px',
    outline: '0',
    transition: 'all 0.2s linear',
    ':hover': {
      backgroundColor: '#005888 !important',
      boxShadow: '0px 2px 0px 0px #011d4f !important',
    },
  },
  iconRightContainer: {
    width: '16px',
    display: 'inline-block',
  },
  iconRightContainerMarginLeft: {
    marginLeft: 10,
  },
  iconRight: {
    maxWidth: '100%',
  },
});


const Button = ({ label, iconRight, style, ...props }) => (
  <button
    className={css(styles.root)}
    style={style}
    {...props}
  >
    {label}
    {iconRight ? (
      <div
        className={css(
          styles.iconRightContainer,
          label && styles.iconRightContainerMarginLeft
        )}
      >
        {React.cloneElement(iconRight, {
          className: css(styles.iconRight),
        })}
      </div>
    ) : null}
  </button>
);

Button.propTypes = {
  label: PropTypes.string,
  iconRight: PropTypes.node,
  style: PropTypes.object,
};

export default Button;

@jameswlane
Copy link

I am working on a new component library and I am using Storybook to display the component. I also ran into this issue. Its been almost a year on this issue, any progress on nailing this bug down?

@IgnusG
Copy link

IgnusG commented Jul 5, 2019

Interesting! I didn't know that React supported that. Unfortunately, there's no way for Aphrodite to know implicitly which frame you are trying to render to, because it isn't connected to React. Maybe we could expose an API like StyleSheet.renderInFrame(frame, () => { ... }) and then it would put the styles in that given frame?

This would be great for styling components inside shadow root containers 👍

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

7 participants