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

Integration with Expo and React native? #618

Closed
GuilhermeGuiuler opened this issue Oct 7, 2023 · 3 comments
Closed

Integration with Expo and React native? #618

GuilhermeGuiuler opened this issue Oct 7, 2023 · 3 comments
Labels
new Flag for new issues before someone replies

Comments

@GuilhermeGuiuler
Copy link

Any way to use it at the expo?
I need to use the onSubmit, onEndingButtonClick functions

@github-actions github-actions bot added the new Flag for new issues before someone replies label Oct 7, 2023
@mathio
Copy link
Contributor

mathio commented Oct 9, 2023

Hello @GuilhermeGuiuler

unfortunately our Embed SDK supports only web environments as it relies on use of <iframe> and postMessage for most of its functionality. My understanding is that React Native does not render web content in iframe, but rather in a WebView.

An alternative solution for you might be to embed a WebView with local HTML page that uses the Embed SDK. Then you would need to connect the static HTML page logic with code in your app - it looks like you should be able to do it via postMessage: https://medium.com/@azharuddin31/react-native-pass-data-to-webview-and-get-data-out-of-webview-792ffbe7eb75

In future, it might be interesting to extend our Embed SDK with such wrapper for React Native. However we do not have any plans like this for now.

@mathio mathio closed this as completed Oct 9, 2023
@louisiscoding
Copy link

louisiscoding commented Nov 21, 2023

Here is my implementation for React Native using WebView and PostMessage.
However, i'm still having an issue as onEndingButtonClick is not catched like onSubmit is

If you guys have any suggestions to update this component, let's collaborate !

/* eslint-disable no-return-assign */
import React, { Component } from 'react';
import { KeyboardAvoidingView, Platform, StyleSheet } from 'react-native';
import { URL } from 'react-native-url-polyfill';
import { WebView, WebViewMessageEvent } from 'react-native-webview';

type TypeformPropType = {
    url: string;
    onSubmit: () => void;
};

type TypeformStateType = {
    isLoaded: boolean;
};

class TypeformEmbed extends Component<TypeformPropType, TypeformStateType> {
    typeformElm: any;
    constructor(props: TypeformPropType) {
        super(props);
        this.state = {
            isLoaded: false,
        };
    }

    onLoad = () => {
        const { url } = this.props;

        const typeformUrl = new URL(url);
        typeformUrl.searchParams.append('typeform-welcome', '0');

        const options = {
            hideHeaders: true,
            hideFooter: true,
            hideScrollbars: true,
            opacity: 0,
        };

        if (this.typeformElm && !this.state.isLoaded) {
            const stringifedOptions = JSON.stringify(JSON.stringify(options));
            const embedCode = `
      {
        const onSubmit = () => window.ReactNativeWebView.postMessage("onSubmit")
        const options = Object.assign({}, JSON.parse(${stringifedOptions}), {onSubmit})
        typeformEmbed.makeWidget(document.getElementById('typeform-embed'), '${typeformUrl}', options)
      }
      true
      `;

            this.typeformElm.injectJavaScript(embedCode);
            this.setState({ isLoaded: true });
        }
    };

    onMessage = (event: WebViewMessageEvent) => {
        const { onSubmit } = this.props;

        const { data } = event.nativeEvent;

        if (data === 'onSubmit') {
            onSubmit();
        }
    };

    render() {
        return (
            <KeyboardAvoidingView style={styles.container} behavior={Platform.OS === 'android' ? 'height' : undefined}>
                <WebView
                    originWhitelist={['*']}
                    ref={el => (this.typeformElm = el)}
                    source={{
                        html: '<html><head><meta name="viewport" content="width=device-width, initial-scale=1.0"><script src="https://embed.typeform.com/embed.js"></script></head><div style={{ height: \'100vh\', width: \'100%\' }} id="typeform-embed" /></html>',
                    }}
                    onLoadEnd={this.onLoad}
                    onMessage={this.onMessage}
                />
            </KeyboardAvoidingView>
        );
    }
}

const styles = StyleSheet.create({
    container: {
        flex: 1,
    },
});

export default TypeformEmbed;

@mathio
Copy link
Contributor

mathio commented Nov 21, 2023

It looks like you are using embed SDK v0 that is no longer supported. You should use current version - you can find it in this repo or at https://embed.typeform.com/next/embed.js. The method to create a widget embed is window.tf.createWidget.

This is a full example:

<div id="wrapper" style="height:400px"></div>
<script src="//embed.typeform.com/next/embed.js"></script>
<script>
  window.tf.createWidget('R0wDakKn', {
    container: document.querySelector('#wrapper'),
    onEndingButtonClick: (payload) => {
      console.log('ending button clicked:', payload)
    }
  })
</script>

Hope this helps.

Do you think a separate library with the react native wrapper would be helpful?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
new Flag for new issues before someone replies
Projects
None yet
Development

No branches or pull requests

3 participants