No Description

index.js 3.1KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. 'use strict';
  2. import React, { PureComponent } from 'react';
  3. import { StyleSheet, Platform, ViewPropTypes } from 'react-native';
  4. import PropTypes from 'prop-types';
  5. import { WebView } from 'react-native-webview';
  6. import {
  7. isEqual,
  8. setState,
  9. getWidth,
  10. isSizeChanged,
  11. handleSizeUpdated,
  12. getStateFromProps,
  13. getBaseScript
  14. } from './utils';
  15. import momoize from './momoize';
  16. export default class AutoHeightWebView extends PureComponent {
  17. static propTypes = {
  18. onSizeUpdated: PropTypes.func,
  19. // 'web/' by default on iOS
  20. // 'file:///android_asset/web/' by default on Android
  21. baseUrl: PropTypes.string,
  22. // add baseUrl/files... to android/app/src/assets/ on android
  23. // add baseUrl/files... to project root on iOS
  24. files: PropTypes.arrayOf(
  25. PropTypes.shape({
  26. href: PropTypes.string,
  27. type: PropTypes.string,
  28. rel: PropTypes.string
  29. })
  30. ),
  31. style: ViewPropTypes.style,
  32. customScript: PropTypes.string,
  33. customStyle: PropTypes.string,
  34. // webview props
  35. originWhitelist: PropTypes.arrayOf(PropTypes.string),
  36. onMessage: PropTypes.func
  37. };
  38. static defaultProps = {
  39. baseUrl: Platform.OS === 'ios' ? 'web/' : 'file:///android_asset/web/'
  40. };
  41. constructor(props) {
  42. super(props);
  43. const { style } = props;
  44. this.webView = React.createRef();
  45. const width = getWidth(style);
  46. const height = style && style.height ? style.height : 1;
  47. this.size = {
  48. oldWidth: width,
  49. oldHeight: height
  50. };
  51. this.state = {
  52. width,
  53. height
  54. };
  55. }
  56. getUpdatedState = momoize(setState, isEqual);
  57. static getDerivedStateFromProps(props, state) {
  58. return getStateFromProps(props, state);
  59. }
  60. onMessage = event => {
  61. if (!event.nativeEvent) {
  62. return;
  63. }
  64. let data = {};
  65. // Sometimes the message is invalid JSON, so we ignore that case
  66. try {
  67. data = JSON.parse(event.nativeEvent.data);
  68. } catch (error) {
  69. console.error(error);
  70. return;
  71. }
  72. const { height, width } = data;
  73. const { oldHeight, oldWidth } = this.size;
  74. if (isSizeChanged(height, oldHeight, width, oldWidth)) {
  75. this.size = {
  76. oldHeight: height,
  77. oldWidth: width
  78. };
  79. this.setState(
  80. {
  81. height,
  82. width
  83. },
  84. () => handleSizeUpdated(height, width, this.props.onSizeUpdated)
  85. );
  86. }
  87. const { onMessage } = this.props;
  88. onMessage && onMessage(event);
  89. };
  90. stopLoading() {
  91. this.webView.current.stopLoading();
  92. }
  93. render() {
  94. const { height, width } = this.state;
  95. const { style, originWhitelist } = this.props;
  96. const { source, script } = this.getUpdatedState(this.props, getBaseScript);
  97. return (
  98. <WebView
  99. {...this.props}
  100. originWhitelist={originWhitelist || ['*']}
  101. ref={this.webView}
  102. onMessage={this.onMessage}
  103. style={[
  104. styles.webView,
  105. {
  106. width,
  107. height
  108. },
  109. style
  110. ]}
  111. injectedJavaScript={script}
  112. source={source}
  113. />
  114. );
  115. }
  116. }
  117. const styles = StyleSheet.create({
  118. webView: {
  119. backgroundColor: 'transparent'
  120. }
  121. });