No Description

index.js 2.9KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121
  1. 'use strict';
  2. import React, { useState, useEffect, useMemo, useRef, useImperativeHandle, forwardRef } 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 { getMemoInputProps, getMemoResult, getWidth, isSizeChanged } from './utils';
  7. const AutoHeightWebView = forwardRef((props, ref) => {
  8. let webView = useRef();
  9. useImperativeHandle(ref, () => ({
  10. stopLoading: () => webView.current.stopLoading()
  11. }));
  12. const { style, onMessage, onSizeUpdated } = props;
  13. const [size, setSize] = useState(() => ({
  14. height: style && style.height ? style.height : 1,
  15. width: getWidth(style)
  16. }));
  17. const hanldeMessage = event => {
  18. if (!event.nativeEvent) {
  19. return;
  20. }
  21. let data = {};
  22. // Sometimes the message is invalid JSON, so we ignore that case
  23. try {
  24. data = JSON.parse(event.nativeEvent.data);
  25. } catch (error) {
  26. console.error(error);
  27. return;
  28. }
  29. const { height, width } = data;
  30. const { height: previousHeight, width: previousWidth } = size;
  31. isSizeChanged({ height, previousHeight, width, previousWidth }) &&
  32. setSize({
  33. height,
  34. width
  35. });
  36. onMessage && onMessage(event);
  37. };
  38. const { source, script } = useMemo(() => getMemoResult(props), [getMemoInputProps(props)]);
  39. const { width, height } = size;
  40. useEffect(
  41. () =>
  42. onSizeUpdated &&
  43. onSizeUpdated({
  44. height,
  45. width
  46. }),
  47. [width, height]
  48. );
  49. return (
  50. <WebView
  51. {...props}
  52. ref={webView}
  53. onMessage={hanldeMessage}
  54. style={[
  55. styles.webView,
  56. {
  57. width,
  58. height
  59. },
  60. style
  61. ]}
  62. injectedJavaScript={script}
  63. source={source}
  64. />
  65. );
  66. });
  67. AutoHeightWebView.propTypes = {
  68. onSizeUpdated: PropTypes.func,
  69. // 'web/' by default on iOS
  70. // 'file:///android_asset/web/' by default on Android
  71. baseUrl: PropTypes.string,
  72. // add baseUrl/files... to android/app/src/assets/ on android
  73. // add baseUrl/files... to project root on iOS
  74. files: PropTypes.arrayOf(
  75. PropTypes.shape({
  76. href: PropTypes.string,
  77. type: PropTypes.string,
  78. rel: PropTypes.string
  79. })
  80. ),
  81. style: ViewPropTypes.style,
  82. customScript: PropTypes.string,
  83. customStyle: PropTypes.string,
  84. // webview props
  85. originWhitelist: PropTypes.arrayOf(PropTypes.string),
  86. onMessage: PropTypes.func
  87. };
  88. let defaultProps = {
  89. originWhitelist: ['*'],
  90. baseUrl: 'web/'
  91. };
  92. Platform.OS === 'android' &&
  93. Object.assign(defaultProps, {
  94. baseUrl: 'file:///android_asset/web/',
  95. // if set to true may cause some layout issues (width of container will be than width of screen) on android
  96. scalesPageToFit: false
  97. });
  98. AutoHeightWebView.defaultProps = defaultProps;
  99. const styles = StyleSheet.create({
  100. webView: {
  101. backgroundColor: 'transparent'
  102. }
  103. });
  104. export default AutoHeightWebView;