如何在 React Native 中重新设置组件的父级?
How to reparent a component in ReactNative?
在下面的代码中,我希望 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>
);
}
}
Link 到 expo snack 在设备上检查它。
到目前为止,我已经阅读了有关在 React 中重新设置父级的问题 here, implementing using Portals, and also saw an issue 关于支持在 React Native 中重新设置父级但没有解决方案。
那么,如何在多个屏幕中重用一个组件实例,而不是在每个屏幕中都创建一个新实例?
希望重新设置父级是答案,但找不到任何实现,所以如果重新设置是这个问题的答案,我该如何实现?
这里的问题是,在每次状态更改时,您的组件都会重新呈现 webView
对象并显示当前日期。我建议您将 webView
更改为一个组件,并在调用 WebViewComp
时添加一个静态键,以防止每次状态更改时 unmount/mount。
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>
);
}
}
您肯定需要重新设置视图的父级。我搜索了一些像 React Portals 一样工作的库。
我们有两个可用的项目:
我测试了第二个包 (rn-native-portals
),这对 Android:
产生了神奇的效果
如何安装
npm install mfrachet/rn-native-portals
react-native link
(不幸的是我们还不能自动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 auto-link 支持以避免编译警告。
更多有用信息:
在下面的代码中,我希望 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>
);
}
}
Link 到 expo snack 在设备上检查它。
到目前为止,我已经阅读了有关在 React 中重新设置父级的问题 here, implementing using Portals, and also saw an issue 关于支持在 React Native 中重新设置父级但没有解决方案。
那么,如何在多个屏幕中重用一个组件实例,而不是在每个屏幕中都创建一个新实例?
希望重新设置父级是答案,但找不到任何实现,所以如果重新设置是这个问题的答案,我该如何实现?
这里的问题是,在每次状态更改时,您的组件都会重新呈现 webView
对象并显示当前日期。我建议您将 webView
更改为一个组件,并在调用 WebViewComp
时添加一个静态键,以防止每次状态更改时 unmount/mount。
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>
);
}
}
您肯定需要重新设置视图的父级。我搜索了一些像 React Portals 一样工作的库。
我们有两个可用的项目:
我测试了第二个包 (rn-native-portals
),这对 Android:
如何安装
npm install mfrachet/rn-native-portals
react-native link
(不幸的是我们还不能自动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 auto-link 支持以避免编译警告。
更多有用信息: