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

hello.js not compatible with ssr and static site generators #597

Open
berkeleycole opened this issue Mar 13, 2019 · 4 comments
Open

hello.js not compatible with ssr and static site generators #597

berkeleycole opened this issue Mar 13, 2019 · 4 comments

Comments

@berkeleycole
Copy link

Hello,

I am rebuilding a client's website with a static site generator (in this case Gatsby js). They are using hello.js but this library depends window being available, which does not exist at build time. I have an idea for a fix, just adding a conditional to ensure the existence of window before running the program, but I wanted to file an issue here first to see if anyone has already worked on this, fixed this, etc..

Does anyone have workarounds for this?

Thanks,
Alyssa

@carloslfu
Copy link
Contributor

carloslfu commented May 19, 2019

I'm experimenting this problem too, what I do is to load it dynamically. For this I created a HOC called WithHelloJS:

function WithHelloJS({ children }) {
  const [hello, setHello] = useState(undefined);
  useEffect(() => {
    import('hellojs').then(mod => {
      setHello(() => mod.default);
    });
  }, []);
  return children({ hello });
}

// then use it

function App() {
  return <div>
    <WithHelloJS>
      {({ hello }) => hello ? <Buttons hello={hello} /> : <></>}
    </WithHelloJS>
  </div>
}

// button uses hellojs
function Buttons({ hello }) {
  useEffect(() => {
    hello.init({ facebook: 'YOUR_APP_ID' });
  }, []);

  const connectToFB = () => {
    hello('facebook')
      .login({
        scope: 'manage_pages,publish_pages',
      }).then(() => {
        alert('Logged-in with Facebook)
      }, () => {
        alert('error');
      });
  };

  const connectToTwitter = () => {
    hello('twitter')
      .login()
      .then(() => {
        alert('Logged-in with Twitter)
      }, () => {
        alert('error');
      });
  };

  return (
    <>
      <button onClick={connectToFB}>Conectar a Facebook</button>
      <button onClick={connectToTwitter}>Conectar a Twitter</button>
    </>
  );
}

Hope it helps.

@carloslfu
Copy link
Contributor

carloslfu commented May 20, 2019

I found the most flexible way is to use a custom hook:

// hello.jsx

import React from 'react';

const HelloContext = React.createContext(undefined);

export function useHello() {
  const context = React.useContext(HelloContext);
  if (!context) {
    throw new Error(`useHello must be used within a HelloProvider`);
  }
  return context;
}

export function HelloProvider(props) {
  const [hello, setHello] = React.useState(undefined);

  React.useEffect(() => {
    import('hellojs').then(mod => {
      setHello(() => mod.default);
    });
  }, []);

  const value = React.useMemo(() => ({ hello }), [hello]);

  return <HelloContext.Provider value={value} {...props} />;
}

// App.js

import React from 'react'
import { HelloProvider } from './hello'
import Page from './Page'

export default () => <HelloProvider>
  <Page />
</HelloProvider>

// Page.js

import React from 'react'
import { useHello } from './hello'

function App() {
  const { hello } = useHello()

  return <div>
    {hello && <Buttons hello={hello} />}
  </div>
}

// button uses hellojs

function Buttons({ hello }) {
  useEffect(() => {
    hello.init({ facebook: 'YOUR_APP_ID' });
  }, []);

  const connectToFB = () => {
    hello('facebook')
      .login({
        scope: 'manage_pages,publish_pages',
      }).then(() => {
        alert('Logged-in with Facebook)
      }, () => {
        alert('error');
      });
  };

  const connectToTwitter = () => {
    hello('twitter')
      .login()
      .then(() => {
        alert('Logged-in with Twitter)
      }, () => {
        alert('error');
      });
  };

  return (
    <>
      <button onClick={connectToFB}>Conectar a Facebook</button>
      <button onClick={connectToTwitter}>Conectar a Twitter</button>
    </>
  );
}

@berkeleycole
Copy link
Author

thanks @carloslfu! I don't know if it will help you, but I also created a pull request to this repo to add conditionals around all references to "document.window" so that we can hopefully just use it as a normal npm package and import it at build time. Don't know if it will be merged yet, but right now I'm using my forked version of this library instead of the official one:
https://github.com/berkeleycole/hello.js

Here is the PR I created in case you want to take a look and see if it will help you:
#600

@carloslfu
Copy link
Contributor

Great, many thanks @berkeleycole!

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

2 participants