7

在下面的代码中,我希望 webView 内容在点击次数增加时不会改变,但每次加载时,都会显示一个新的时间戳。

const webView = (
  <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>
        <Text onPress={this.onClick}>
          Click Me: {this.state.clicks}
        </Text>

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

链接到博览会小吃以在设备上进行检查。

到目前为止,我已经阅读了 React 中关于问题的 reparenting 使用 Portals 实现,并且还看到了一个关于在 react native 中支持 reparenting 的问题,但没有解决方案

那么,如何在多个屏幕中重用组件实例而不在每个屏幕中创建它的新实例呢?

希望reparenting是答案,但找不到任何实现,所以如果reparenting是这个问题的答案,如何自己实现它?

4

2 回答 2

3

这里的问题是,在每次状态更改时,您的组件都会重新渲染webView对象并显示当前日期。我建议您webView在调用时更改为组件并添加静态键,WebViewComp以防止每次状态更改时卸载/挂载。

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>
    );
  }
}
于 2020-05-15T13:23:11.390 回答
2

您肯定需要重新设置视图。我搜索了一些与 React Portals 一样工作的库。

我们有两个项目可用:

我测试了第二个包(rn-native-portals),这在 Android 上神奇地工作:

如何安装

  1. npm install mfrachet/rn-native-portals

  2. react-native link(不幸的是我们还不能自动链接这个,但我们可以提交 PR)

执行

您的目标元素需要在里面<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;

在目的地使用这个(不要忘记设置相同的唯一门户名称)

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

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

export default Destination;

这个项目很棒,但绝对需要我们的社区帮助来创建更好的文档。

我有一个项目需要使用此功能,将视频重新设置到屏幕外部。我正在认真考虑 PR 自动链接支持以避免编译警告。

更多有用的信息:

于 2020-05-21T02:25:13.653 回答