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

reactNativeDriver - Why is Root not wrapped with createElement? #15

Open
Javaherr opened this issue Oct 12, 2018 · 5 comments
Open

reactNativeDriver - Why is Root not wrapped with createElement? #15

Javaherr opened this issue Oct 12, 2018 · 5 comments

Comments

@Javaherr
Copy link

reactNativeDriver() function in the current state is not mounting the app/running the application unless there is an initial emission on the stream to do the mounting of the app.

Is it because of missing createElement to be called on Root?
react-dom driver works fine because root was wrapped with createElement(Root) before mounting to container, while the react-native driver doesn't do it before registering component why?

AppRegistry.registerComponent(appKey, () => Root);

https://github.com/cyclejs/react-dom/blob/e1e5da8e998854344acdc117278e9c773ffecca3/src/index.ts#L10

André @staltz will it fix the react native app initial mounting problem? I don't know, I would like to learn.

@staltz
Copy link
Member

staltz commented Oct 12, 2018

Hi, if I understood your question correctly, this is simply how React Native works. Instead of calling "render", you just pass the App component (i.e. Root) to registerComponent, and it's up to React Native to call createElement.

@Javaherr
Copy link
Author

Javaherr commented Oct 12, 2018

Hi André,
Thanks for looking into it and explaining this thing. I know you are very busy.
Let me explain what I am encountering.

import xs from 'xstream';
import {run} from '@cycle/run';
import {makeReactNativeDriver, TouchableOpacity, View, Text} from '@cycle/react-native';

// Just as explained in the repo example. Doesn't run the app
// function main(sources) {
//   const inc = Symbol();
//   const inc$ = sources.react.select(inc).events('press');

//   const count$ = inc$.fold(count => count + 1, 0);

//   const elem$ = count$.map(i =>
//     TouchableOpacity(inc, [
//       View([
//         Text(`Counter: ${i}`),
//       ])
//     ]),
//   ).debug('elem$');

//   return {
//     react: elem$,
//   };
// }


function main(sources) {
    const inc = Symbol();
    const inc$ = sources.react.select(inc).events('press');

    const count$ = inc$.fold(count => count + 1, 0);

    // Case0 Just as explained in the repo example. Doesn't run the app
    // Emission of react element happening before Running application / mounting application
    const case0$ = count$.map(i =>
        TouchableOpacity(inc, [
        View({style: TestStyle},[
            Text(`Counter: ${i}`),
            ])
        ]),
    ).debug('elem$');
  
    // Case1 Immediate emission. Doesn't run the app
    // Same as Case 0 Emission of react element happening before Running application / mounting application
    const case1$ = xs.of(
        TouchableOpacity(inc, [
            View([
              Text(`Counter`),
            ])
          ])
    ).debug('case1$')
    
    // Case2 Periodic emission. Works.
    // This case actually emits react element after running application/ mounting application and works
    // What I noticed was that unless there is a periodic emission from the react stream the
    // react native driver is not mounting the application.
    const case2$ = xs.periodic(1).take(1).map(counter => {
        return (
            TouchableOpacity(inc, [
                View({style: TestStyle},[
                  Text(`Counter: ${counter}`),
                ])
              ])
        )
    }).debug('case2$')

    inc$.addListener({
        next: e => console.log('pressed event')
    })
  
    return {
      react: case2$,
    };
  }

run(main, {
  react: makeReactNativeDriver('rncycle1'),
});

const TestStyle = {
    display:'flex',
    flexDirection:'column',
    justifyContent:'center',
    alignItems:'center',
    backgroundColor: '#FFF176',
    justifyContent: 'center',
    height: 100
}

@barrerajose
Copy link

barrerajose commented Oct 19, 2018

Hi André,
New to cycle, trying to create a react native app using it. The example you have on the readme.md does not work, it renders a blank screen. Also, I don't think it is events('click'), but events('press')... please advice!
Thanks

@Powersource
Copy link

Having a similar problem, I think, but I'm also trying to use react-native-web https://gitlab.com/staltz/manyverse/-/merge_requests/139#note_478788767

@mhhf
Copy link

mhhf commented Feb 2, 2021

I'm late to the party but in case its still relevant: also stumbled about this problem and could dig a little deeper (on android): because in the the ReactNative app talks through a callback with the java implementation during the setup phase it takes longer to initialize then the cyclejs code and hence the initial rendering is missed by it. @Javaherr's case2 example works because periodic has a timed delay build in.
I'm using it with somewhat ugly workaround, which makes all the examples work:
instead of:

import {run} from '@cycle/run';
[...]
run(main, {
  react: makeReactNativeDriver('rncycle1'),
});

one cold use:

import {setup} from '@cycle/run';
import {AppRegistry} from "react-native";
// [...]
var cb;
const registerRootComponent = Root => {
  return AppRegistry.registerComponent("myapp", () => {
    cb();
    return Root
  });
}
cb = setup(main, {
  react: makeReactNativeDriver("myapp", { registerRootComponent })
}).run

or

import {setup} from '@cycle/run';
// [...]
const program = setup(main, {
  react: makeReactNativeDriver("myapp")
})
setTimeout(() => {program.run()}, 10);

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

5 participants