ソースを参照

use React.memo instead of useMemo

iou90kant 4 年 前
コミット
978c33b8bc
共有2 個のファイルを変更した94 個の追加76 個の削除を含む
  1. 75
    75
      autoHeightWebView/index.js
  2. 19
    1
      autoHeightWebView/utils.js

+ 75
- 75
autoHeightWebView/index.js ファイルの表示

@@ -1,6 +1,6 @@
1 1
 'use strict';
2 2
 
3
-import React, { useState, useEffect, useMemo, useRef, useImperativeHandle, forwardRef } from 'react';
3
+import React, { useState, useEffect, useRef, useImperativeHandle, forwardRef } from 'react';
4 4
 
5 5
 import { StyleSheet, Platform, ViewPropTypes } from 'react-native';
6 6
 
@@ -8,80 +8,80 @@ import PropTypes from 'prop-types';
8 8
 
9 9
 import { WebView } from 'react-native-webview';
10 10
 
11
-import { getMemoResult, getWidth, isSizeChanged } from './utils';
12
-
13
-const AutoHeightWebView = forwardRef((props, ref) => {
14
-  let webView = useRef();
15
-  useImperativeHandle(ref, () => ({
16
-    stopLoading: () => webView.current.stopLoading(),
17
-    goForward: () => webView.current.goForward(),
18
-    goBack: () => webView.current.goBack(),
19
-    reload: () => webView.current.reload(),
20
-    injectJavaScript: script => webView.current.injectJavaScript(script)
21
-  }));
22
-
23
-  const { style, onMessage, onSizeUpdated, source, baseUrl, files, customStyle, customScript, zoomable } = props;
24
-
25
-  const [size, setSize] = useState(() => ({
26
-    height: style && style.height ? style.height : 0,
27
-    width: getWidth(style)
28
-  }));
29
-  const hanldeMessage = event => {
30
-    onMessage && onMessage(event);
31
-    if (!event.nativeEvent) {
32
-      return;
33
-    }
34
-    let data = {};
35
-    // Sometimes the message is invalid JSON, so we ignore that case
36
-    try {
37
-      data = JSON.parse(event.nativeEvent.data);
38
-    } catch (error) {
39
-      console.error(error);
40
-      return;
41
-    }
42
-    const { height, width } = data;
43
-    const { height: previousHeight, width: previousWidth } = size;
44
-    isSizeChanged({ height, previousHeight, width, previousWidth }) &&
45
-      setSize({
46
-        height,
47
-        width
48
-      });
49
-  };
50
-
51
-  const { currentSource, script } = useMemo(
52
-    () => getMemoResult({ source, baseUrl, files, customStyle, customScript, zoomable }),
53
-    [source, baseUrl, files, customStyle, customScript, zoomable]
54
-  );
55
-
56
-  const { width, height } = size;
57
-  useEffect(
58
-    () =>
59
-      onSizeUpdated &&
60
-      onSizeUpdated({
61
-        height,
62
-        width
63
-      }),
64
-    [width, height, onSizeUpdated]
65
-  );
66
-
67
-  return (
68
-    <WebView
69
-      {...props}
70
-      ref={webView}
71
-      onMessage={hanldeMessage}
72
-      style={[
73
-        styles.webView,
74
-        {
75
-          width,
76
-          height
77
-        },
78
-        style
79
-      ]}
80
-      injectedJavaScript={script}
81
-      source={currentSource}
82
-    />
83
-  );
84
-});
11
+import { reduceData, getWidth, isSizeChanged, shouldUpdate } from './utils';
12
+
13
+const AutoHeightWebView = React.memo(
14
+  forwardRef((props, ref) => {
15
+    let webView = useRef();
16
+    useImperativeHandle(ref, () => ({
17
+      stopLoading: () => webView.current.stopLoading(),
18
+      goForward: () => webView.current.goForward(),
19
+      goBack: () => webView.current.goBack(),
20
+      reload: () => webView.current.reload(),
21
+      injectJavaScript: script => webView.current.injectJavaScript(script)
22
+    }));
23
+
24
+    const { style, onMessage, onSizeUpdated, source, baseUrl, files, customStyle, customScript, zoomable } = props;
25
+
26
+    const [size, setSize] = useState(() => ({
27
+      height: style && style.height ? style.height : 0,
28
+      width: getWidth(style)
29
+    }));
30
+    const hanldeMessage = event => {
31
+      onMessage && onMessage(event);
32
+      if (!event.nativeEvent) {
33
+        return;
34
+      }
35
+      let data = {};
36
+      // Sometimes the message is invalid JSON, so we ignore that case
37
+      try {
38
+        data = JSON.parse(event.nativeEvent.data);
39
+      } catch (error) {
40
+        console.error(error);
41
+        return;
42
+      }
43
+      const { height, width } = data;
44
+      const { height: previousHeight, width: previousWidth } = size;
45
+      isSizeChanged({ height, previousHeight, width, previousWidth }) &&
46
+        setSize({
47
+          height,
48
+          width
49
+        });
50
+    };
51
+
52
+    const { currentSource, script } = reduceData({ source, baseUrl, files, customStyle, customScript, zoomable });
53
+
54
+    const { width, height } = size;
55
+    useEffect(
56
+      () =>
57
+        onSizeUpdated &&
58
+        onSizeUpdated({
59
+          height,
60
+          width
61
+        }),
62
+      [width, height, onSizeUpdated]
63
+    );
64
+
65
+    return (
66
+      <WebView
67
+        {...props}
68
+        ref={webView}
69
+        onMessage={hanldeMessage}
70
+        style={[
71
+          styles.webView,
72
+          {
73
+            width,
74
+            height
75
+          },
76
+          style
77
+        ]}
78
+        injectedJavaScript={script}
79
+        source={currentSource}
80
+      />
81
+    );
82
+  }),
83
+  (prevProps, nextProps) => !shouldUpdate({ prevProps, nextProps })
84
+);
85 85
 
86 86
 AutoHeightWebView.propTypes = {
87 87
   onSizeUpdated: PropTypes.func,

+ 19
- 1
autoHeightWebView/utils.js ファイルの表示

@@ -116,7 +116,7 @@ export const isSizeChanged = ({ height, previousHeight, width, previousWidth })
116 116
   return height !== previousHeight || width !== previousWidth;
117 117
 };
118 118
 
119
-export const getMemoResult = props => {
119
+export const reduceData = props => {
120 120
   const { source, baseUrl } = props;
121 121
   const script = getScript(props);
122 122
   let currentSource = baseUrl ? { baseUrl } : {};
@@ -131,3 +131,21 @@ export const getMemoResult = props => {
131 131
     };
132 132
   }
133 133
 };
134
+
135
+export const shouldUpdate = ({ prevProps, nextProps }) => {
136
+  if (!(prevProps && nextProps)) {
137
+    return true;
138
+  }
139
+  for (const prop in nextProps) {
140
+    if (nextProps[prop] !== prevProps[prop]) {
141
+      if (typeof nextProps[prop] === 'object' && typeof prevProps[prop] === 'object') {
142
+        if (shouldUpdate({ prevProps: prevProps[prop], nextProps: nextProps[prop] })) {
143
+          return true;
144
+        }
145
+      } else {
146
+        return true;
147
+      }
148
+    }
149
+  }
150
+  return false;
151
+};