注:我是react-native-render-html__的作者。这个问题是为了教育目的,https://stackoverflow.blog/2011/07/01/its-ok-to-ask-and-answer-your-own-questions/。

我在一个RenderHtml组件中呈现WebDisplay组件,如下所示:
import * as React from 'react';
import {ScrollView, StyleSheet, Text, useWindowDimensions} from 'react-native';
import RenderHtml from 'react-native-render-html';
const html = '<div>Hello world!</div>';
function WebDisplay({html}) {
const {width: contentWidth} = useWindowDimensions();
const tagsStyles = {
a: {
textDecorationLine: 'none',
},
};
return (
<RenderHtml
contentWidth={contentWidth}
source={{html}}
tagsStyles={tagsStyles}
/>
);
}
export default function App() {
const [isToastVisible, setIsToastVisible] = React.useState(false);
React.useEffect(function flipToast() {
const timeout = setTimeout(() => {
setIsToastVisible((v) => !v);
}, 30);
return () => {
clearTimeout(timeout);
};
});
return (
<ScrollView contentContainerStyle={styles.container}>
<WebDisplay html={html} />
{isToastVisible && <Text>This is a toast!</Text>}
</ScrollView>
);
}
const styles = StyleSheet.create({
container: {
flexGrow: 1,
},
});为什么我会收到这样的警告,这意味着什么,以及如何修正它?
发布于 2021-08-28 16:09:31
通常,此警告会在下列情况下显示:
App)经常更新,并导致WebDisplay组件重新呈现。在提供的片段中,每30毫秒一次;RenderHTML的至少一个支柱在每个重呈现之间都是参照不稳定的。在所提供的片段中,每次重呈现时都会更改tagsStyles引用。注意,在每次更新由App挂钩引起的useEffect组件之间,传递给WebDisplay的html支柱没有变化。但是WebDisplay被重新呈现,因为它不是“纯”的。
出于这个原因,一个非常简单的解决方案是将WebDisplay封装在React.memo中。
const WebDisplay = React.memo(function WebDisplay({html}) {
const {width: contentWidth} = useWindowDimensions();
const tagsStyles = {
a: {
textDecorationLine: 'none',
},
};
return (
<RenderHtml
contentWidth={contentWidth}
source={{html}}
tagsStyles={tagsStyles}
/>
);
});您可以了解更多关于这种技术的在正式文件中。
Note:“纯”术语来自React PureComponent类。我认为
React.pure不会像React.memo那样模棱两可,因为我们现在使用“回忆录”来指定应用于组件和道具的优化技术,这可能会让人感到困惑。我更喜欢为组件保留“纯”术语,为道具保留“回忆录”。
另一种解决方案是将tagsStyles移出WebDisplay函数体。在这种情况下,它将只实例化一次,并成为引用稳定的。因为RenderHtml本身是纯的,所以它不会重新呈现自己的子组件,因此警告应该消失:
const tagsStyles = {
a: {
textDecorationLine: 'none',
},
};
function WebDisplay({html}) {
const {width: contentWidth} = useWindowDimensions();
return (
<RenderHtml
contentWidth={contentWidth}
source={{html}}
tagsStyles={tagsStyles}
/>
);
};Note:移动任何不依赖于功能组件主体之外的任何其他状态或支持的道具是一个很好的习惯。
最后,如果您的用例涉及到tagsStyles (取决于一个道具),您可以使用React.useMemo回溯它。
function WebDisplay({html, anchorColor}) {
const {width: contentWidth} = useWindowDimensions();
const tagsStyles = React.useMemo(
() => ({
a: {
color: anchorColor,
textDecorationLine: 'none',
},
}),
[anchorColor],
);
return (
<RenderHtml
contentWidth={contentWidth}
source={{html}}
tagsStyles={tagsStyles}
/>
);
}关于这个钩子在正式文件中的更多信息。
如果你还没有一个清晰的心理模型来解释组件更新是如何反应的,我建议你通过这些阅读来提高你的技能:
发布于 2022-06-15 23:27:53
把这个道具,enableExperimentalBRCollapsing={true},从<RenderHtml />上移走,为我工作。
https://stackoverflow.com/questions/68966120
复制相似问题