facebookarchive / react-360

Create amazing 360 and VR content using React
https://facebook.github.io/react-360
Other
8.73k stars 1.22k forks source link

Add React360 to a Larger JS App #477

Open pagonzal13 opened 6 years ago

pagonzal13 commented 6 years ago

Description

I've read at React360 documentation that you can integrate your React360 app into an Existing Web Site not just embedding via Iframe, but also adding it to a Larger JS App. I've a ReactJS app (with Redux too) and I cannot find any example with the second option. Where I have to place the code of client.js file? Wich DOM node should attach my React360 code to? Do I have to copy my entire React360 app folder into the larger one?

With the information at the official documentation I understand that it can be done, but i don't get how to it and there isn't any example.

Additional Information

towfiqi commented 5 years ago

Any update on this? I am having the same confusion. The doc is not helpful..

wdeng commented 5 years ago

I have the same problem. Or maybe we can use iframe and somehow pass context/events in and out of the React360 app?

pagonzal13 commented 5 years ago

I finally did it with an iframe and using NativeModules and window.postMessage()

overide commented 5 years ago

@pagonzal13 Can you please explain how you achieved it?

pagonzal13 commented 5 years ago

@overide

In the following link is the memory of my final project, in which I had to use the iframe solution. Specifically on pages 26-32: http://oa.upm.es/52001/1/PFC_PAULA_GONZALEZ_GOMEZ_2018.pdf In my case I needed to send different types of data between the two windows and that's why it seems more complex, but the mechanism is simple. I have tried to simplify it to make it easier to understand:

Step 1: React360 application (client.js) --> import ConexionModule from './ConexionModule'; function init(bundle, parent, options = {}) {const r360 = new ReactInstance(bundle, parent, {nativeModules: [ctx => new ConexionModule(ctx),],...options,});

Step 2: React360 application (ConexionModule) --> let query = decodeURIComponent(window.location.search); try{window.parent.postMessage(JSON.stringify({msg: 'LOAD' }),"*");} catch(e){console.log(e);}

Step 3: Larger application (iframe) --> let dataNeeded = {imageURL: urlimage, text: dataString}; window.addEventListener("message", this.receiver); receiver(e) { try{ let data = JSON.parse(e.data); if (!this.windowSource && data.msg === 'LOAD') { this.windowSource = e.source; this.useDataFromReact360(); } } catch (err) { console.error(err);} } useDataFromReact360 (dataNeeded = this.dataNeeded) { let receiverWindow = this.windowSource; if(receiverWindow) { let {imageURL, text} = dataNeeded; receiverWindow.postMessage({ msg: 'DATA', imageURL, text}, ""); } } receiver(e) {   try{   let data = JSON.parse(e.data);       if (!this.windowSource && data.msg === 'LOAD') {   this.windowSource = e.source;   this.useDataFromReact360();   }  } catch (err) {console.error(err);} } useDataFromReact360 (dataNeeded = this.dataNeeded) {   let receiverWindow = this.windowSource;   if(receiverWindow) {   let {imageURL, text} = dataNeeded;   receiverWindow.postMessage({ msg: 'DATA', imageURL, text}, "");   } }

Step 4: React360 application (ConexionModule) --> import {Module} from 'react-360-web'; let idBox = null; export default class ConexionModule extends Module { constructor(ctx) { super('ConexionModule'); // Makes this module available at NativeModules.MyModule this._rnctx = ctx; this.winSource = undefined; this.origin = undefined; } conexionIframe(callback) { const result = new Promise((resolve, reject) => {window.addEventListener("message", function(event) { this.winSource = event.source; this.origin = event.origin; resolve(event.data);}), function e(){console.log("Problems with promise");};}); result.then(datos => {if (this._rnctx) {this._rnctx.invokeCallback(cb, [datos]);}});
//paste here step 2
}

Step 5: React360 application (index.js) --> // Extract our custom native module const ConexionModule = NativeModules.ConexionModule; constructor() {super(); this.state = {img: undefined,text: undefined,}; this.escucharConexion=this.escucharConexion.bind(this); } escucharConexion() {ConexionModule.conexionIframe(datos => { if(datos. imageURL){this.setState({img: datos. imageURL});} if(datos. text){this.setState({text: datos. text});} this.escucharConexion();}); } componentDidMount() { this.escucharConexion(); }

I hope it's useful to you. Any doubt, don't hesitate to ask me.

mvallejo3 commented 5 years ago

Has anyone figured this one out? I integrate the client js code to my React App and i get a compiling error. The type declarations used in react-360-web in node_modules throughs an error. I cannot figure out why. - https://screencast.com/t/tbk0QRVW

A-Kasaaian commented 5 years ago

@pagonzal13 Thank you for your solution, it fulfils my requirements.

josepaulodelacruz commented 5 years ago

ISSUE: 172 SOLVE ISSUE: NONE facebook doesn't give a sh*t about react 360 My apologies for the rant.. im just pissed I spend 1 whole day with this problem ill try your solution Thanks for sharing your solution

clydekarnage commented 4 years ago

@pagonzal13 do still have the repo of your project? care to share?