How to reparent a component in ReactNative?

The problem here is that on every state change your component will re-render webView object and will show the current date. I suggest that you change webView to a component and add a static key when you call WebViewComp to prevent unmount/mount on every state change.

const WebViewComp = () => ( //Change declaration to function component instead of constant object
  <WebView
    source={{
      uri:
        'data:text/html,<html><script>document.write("<h1 style=\\"font-size:64px\\">"+Date.now()+"<h1>");</script>',
    }}
  />
);

export default class App extends React.Component {
  state = {
    clicks: 0,
  };

  onClick = () => {
    this.setState({ clicks: this.state.clicks + 1 });
  };

  render() {
    return (
      <View style={styles.container}>
        <Text style={styles.paragraph} onPress={this.onClick}>
          Click Me: {this.state.clicks}
        </Text>

        {this.state.clicks % 2 === 0 ? <WebViewComp key="child" /> : null}
        {this.state.clicks % 2 === 1 ? <WebViewComp key="child" /> : null}
      </View>
    );
  }
}

You definitely need to reparenting the view. I searched some libs that work as React Portals does.

We have two projects available:

  • https://github.com/zenyr/react-native-portal

  • https://github.com/mfrachet/rn-native-portals

I tested the second package (rn-native-portals) and this magically worked on Android:

How to install

  1. npm install mfrachet/rn-native-portals

  2. react-native link (unfortunately we can't auto-link this yet, but we can submit PR)

Implementation

Your target element needs to be inside <PortalOrigin>

import React from "react";
import { View, Text, TouchableOpacity } from "react-native";
import { PortalOrigin } from 'rn-native-portals';

class Target extends React.Component {
  state = {
    moveView: false,
  }

  render() {
    return (
      <>
        <TouchableOpacity
          style={{ flex: 1 }}
          onPress={() => this.setState({ moveView: !this.state.moveView })}
        >
          <Text>Press Here</Text>
        </TouchableOpacity>

        <PortalOrigin destination={this.state.moveView ? 'destinationPortal' : null}>
          <View>
            <Text>This text will appear on destination magically...</Text>
          </View>
        </PortalOrigin>
      </>
    );
  }
}

export default Target;

On destination use this (don't forget set the same unique portal's name)

import React from "react";
import { PortalDestination } from "rn-native-portals";

class Destination extends React.Component {
  render() {
    return (
      <PortalDestination name="destinationPortal" />
    );
  }
}

export default Destination;

This project is amazing, but definitely need our community help to create a better documentation.

I have one project that need to use this feature, reparenting a video to the outside of screen. I'm seriously considering PR auto-link support to avoid compiling warnings.

More useful info about:

  • The project concept: https://github.com/mfrachet/rn-native-portals/blob/master/docs/CONCEPT.md

  • Why the project was created (long history): https://tech.bedrockstreaming.com/6play/how-a-fullscreen-video-mode-ended-up-implementing-react-native-portals/