@samitouri / QOS-React-2 / commits / bec073365d

Fix hooks warnings identified by prerelease version of react-hooks ESLint plugin

Brian Vaughn committed Feb 19, 2019 at 13:15 UTC bec073365d14aba07ff98a589ab52301761e7a72
8 files changed +72 -38
shells/dev/app/ToDoList/List.js
+1 -1
@@ -34,7 +34,7 @@ export default function List(props: Props) {
34 setUID(uid + 1);
35 setNewItemText('');
36 }
37 - }, [newItemText]);
37 + }, [newItemText, items, uid]);
38
39 const handleKeyPress = useCallback(
40 event => {
src/devtools/views/Element.js
+23 -10
@@ -25,22 +25,35 @@ export default function ElementView({ index, style }: Props) {
25
26 const element = getElementAtIndex(index);
27
28 - if (element == null) {
29 - console.warn(`<ElementView> Could not find element at index ${index}`);
30 - return null;
31 - }
32 -
33 - const { depth, displayName, id, key, type } = ((element: any): Element);
28 + const id = element === null ? null : element.id;
29
35 - const handleDoubleClick = useCallback(() => selectOwner(id), [id]);
30 + const handleDoubleClick = useCallback(() => {
31 + if (id !== null) {
32 + selectOwner(id);
33 + }
34 + }, [id, selectOwner]);
35
36 // TODO Add click and key handlers for toggling element open/close state.
37
38 const handleClick = useCallback(
40 - ({ metaKey }) => selectElementByID(metaKey ? null : id),
41 - [id]
39 + ({ metaKey }) => {
40 + if (id !== null) {
41 + selectElementByID(metaKey ? null : id);
42 + }
43 + },
44 + [id, selectElementByID]
45 );
46
47 + // Handle elements that are removed from the tree while an async render is in progress.
48 + if (element == null) {
49 + console.warn(`<ElementView> Could not find element at index ${index}`);
50 +
51 + // This return needs to happen after hooks, since hooks can't be conditional.
52 + return null;
53 + }
54 +
55 + const { depth, displayName, key, type } = ((element: any): Element);
56 +
57 const isSelected = selectedElementID === id;
58 const showDollarR =
59 isSelected && (type === ElementTypeClass || type === ElementTypeFunction);
@@ -58,7 +71,7 @@ export default function ElementView({ index, style }: Props) {
71 }}
72 >
73 <span className={styles.Component}>
61 - <DisplayName displayName={displayName} id={id} />
74 + <DisplayName displayName={displayName} id={((id: any): number)} />
75 {key && (
76 <Fragment>
77 &nbsp;<span className={styles.AttributeName}>key</span>=
src/devtools/views/InspectedElementTree.js
+1 -1
@@ -183,7 +183,7 @@ function EditableValue({
183 setEditableValue(target.value);
184 }
185 },
186 - [dataType, setEditableValue]
186 + [dataType, overrideValueFn, path]
187 );
188
189 const handleKeyPress = useCallback(
src/devtools/views/SelectedElement.js
+6 -3
@@ -43,7 +43,7 @@ export default function SelectedElement(_: Props) {
43 });
44 }
45 }
46 - }, [bridge, selectedElementID, store]);
46 + }, [bridge, element, selectedElementID, store]);
47
48 // TODO Make "view source" button work
49
@@ -176,7 +176,10 @@ function InspectedElementView({
176 function OwnerView({ displayName, id }: { displayName: string, id: number }) {
177 const { selectElementByID } = useContext(TreeContext);
178
179 - const handleClick = useCallback(() => selectElementByID(id), [id]);
179 + const handleClick = useCallback(() => selectElementByID(id), [
180 + id,
181 + selectElementByID,
182 + ]);
183
184 return (
185 <div
@@ -260,7 +263,7 @@ function useInspectedElement(id: number | null): InspectedElement | null {
263
264 bridge.removeListener('inspectedElement', onInspectedElement);
265 };
263 - }, [id]);
266 + }, [bridge, id, idRef, store]);
267
268 return inspectedElement;
269 }
src/devtools/views/SettingsContext.js
+9 -2
@@ -76,7 +76,7 @@ function SettingsContextController({ browserTheme, children }: Props) {
76 default:
77 throw Error(`Unsupported theme value "${theme}"`);
78 }
79 - }, [theme]);
79 + }, [browserTheme, theme]);
80
81 const value = useMemo(
82 () => ({
@@ -89,7 +89,14 @@ function SettingsContextController({ browserTheme, children }: Props) {
89 ? compactLineHeight
90 : comfortableLineHeight,
91 }),
92 - [displayDensity, setDisplayDensity, theme, setTheme]
92 + [
93 + comfortableLineHeight,
94 + compactLineHeight,
95 + displayDensity,
96 + setDisplayDensity,
97 + setTheme,
98 + theme,
99 + ]
100 );
101
102 return (
src/devtools/views/Tree.js
+1 -5
@@ -63,11 +63,7 @@ export default function Tree(props: Props) {
63 return () => {
64 window.removeEventListener('keydown', handleKeyDown);
65 };
66 - }, [
67 - selectedElementIndex,
68 - selectNextElementInTree,
69 - selectPreviousElementInTree,
70 - ]);
66 + }, [selectNextElementInTree, selectPreviousElementInTree]);
67
68 // Let react-window know to re-render any time the underlying tree data changes.
69 // This includes the owner context, since it controls a filtered view of the tree.
src/devtools/views/TreeContext.js
+14 -2
@@ -595,7 +595,19 @@ function TreeContextController({ children }: {| children: React$Node |}) {
595 resetOwnerStack,
596 selectOwner,
597 }),
598 - [state]
598 + [
599 + getElementAtIndex,
600 + goToNextSearchResult,
601 + goToPreviousSearchResult,
602 + resetOwnerStack,
603 + selectElementAtIndex,
604 + selectElementByID,
605 + selectNextElementInTree,
606 + selectOwner,
607 + selectPreviousElementInTree,
608 + setSearchText,
609 + state,
610 + ]
611 );
612
613 // Listen for host element selections.
@@ -632,7 +644,7 @@ function TreeContextController({ children }: {| children: React$Node |}) {
644 store.addListener('mutated', handleStoreMutated);
645
646 return () => store.removeListener('mutated', handleStoreMutated);
635 - }, [dispatch, store]);
647 + }, [dispatch, initialRevision, store]);
648
649 return <TreeContext.Provider value={value}>{children}</TreeContext.Provider>;
650 }
src/devtools/views/hooks.js
+17 -14
@@ -1,13 +1,13 @@
1 // @flow
2
3 -import { useLayoutEffect, useState } from 'react';
3 +import { useCallback, useLayoutEffect, useState } from 'react';
4
5 // Forked from https://usehooks.com/useLocalStorage/
6 export function useLocalStorage<T>(
7 key: string,
8 initialValue: T
9 ): [T, (value: T | (() => T)) => void] {
10 - const getValueFromLocalStorage = () => {
10 + const getValueFromLocalStorage = useCallback(() => {
11 try {
12 const item = window.localStorage.getItem(key);
13 return item ? JSON.parse(item) : initialValue;
@@ -15,20 +15,23 @@ export function useLocalStorage<T>(
15 console.log(error);
16 return initialValue;
17 }
18 - };
18 + }, [initialValue, key]);
19
20 const [storedValue, setStoredValue] = useState(getValueFromLocalStorage);
21
22 - const setValue = value => {
23 - try {
24 - const valueToStore =
25 - value instanceof Function ? value(storedValue) : value;
26 - setStoredValue(valueToStore);
27 - window.localStorage.setItem(key, JSON.stringify(valueToStore));
28 - } catch (error) {
29 - console.log(error);
30 - }
31 - };
22 + const setValue = useCallback(
23 + value => {
24 + try {
25 + const valueToStore =
26 + value instanceof Function ? value(storedValue) : value;
27 + setStoredValue(valueToStore);
28 + window.localStorage.setItem(key, JSON.stringify(valueToStore));
29 + } catch (error) {
30 + console.log(error);
31 + }
32 + },
33 + [key, storedValue]
34 + );
35
36 // Listen for changes to this local storage value made from other windows.
37 // This enables the e.g. "⚛️ Elements" tab to update in response to changes from "⚛️ Settings".
@@ -45,7 +48,7 @@ export function useLocalStorage<T>(
48 return () => {
49 window.removeEventListener('storage', onStorage);
50 };
48 - }, [key, storedValue]);
51 + }, [getValueFromLocalStorage, key, storedValue, setValue]);
52
53 return [storedValue, setValue];
54 }