[Security Solution] Refactor useSelector (#75297)

This commit is contained in:
Patryk Kopyciński 2020-09-28 15:28:11 +02:00 committed by GitHub
parent 53d49381c8
commit 2defe88a2c
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
33 changed files with 135 additions and 131 deletions

View file

@ -5,13 +5,13 @@
*/ */
import React, { useState, useCallback, useMemo } from 'react'; import React, { useState, useCallback, useMemo } from 'react';
import { useDispatch } from 'react-redux';
import { useDispatch, useSelector } from 'react-redux'; import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { APP_ID } from '../../../../common/constants'; import { APP_ID } from '../../../../common/constants';
import { SecurityPageName } from '../../../app/types'; import { SecurityPageName } from '../../../app/types';
import { useKibana } from '../../../common/lib/kibana'; import { useKibana } from '../../../common/lib/kibana';
import { getCaseDetailsUrl, getCreateCaseUrl } from '../../../common/components/link_to'; import { getCaseDetailsUrl, getCreateCaseUrl } from '../../../common/components/link_to';
import { State } from '../../../common/store';
import { setInsertTimeline } from '../../../timelines/store/timeline/actions'; import { setInsertTimeline } from '../../../timelines/store/timeline/actions';
import { timelineSelectors } from '../../../timelines/store/timeline'; import { timelineSelectors } from '../../../timelines/store/timeline';
@ -34,7 +34,7 @@ export const useAllCasesModal = ({
}: UseAllCasesModalProps): UseAllCasesModalReturnedValues => { }: UseAllCasesModalProps): UseAllCasesModalReturnedValues => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { navigateToApp } = useKibana().services.application; const { navigateToApp } = useKibana().services.application;
const timeline = useSelector((state: State) => const timeline = useShallowEqualSelector((state) =>
timelineSelectors.selectTimeline(state, timelineId) timelineSelectors.selectTimeline(state, timelineId)
); );

View file

@ -4,17 +4,16 @@
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
import { isEqual } from 'lodash/fp';
import { useMemo } from 'react'; import { useMemo } from 'react';
import { useSelector } from 'react-redux';
import { useDeepEqualSelector } from '../../hooks/use_selector';
import { makeMapStateToProps } from '../url_state/helpers'; import { makeMapStateToProps } from '../url_state/helpers';
import { getSearch } from './helpers'; import { getSearch } from './helpers';
import { SearchNavTab } from './types'; import { SearchNavTab } from './types';
export const useGetUrlSearch = (tab: SearchNavTab) => { export const useGetUrlSearch = (tab: SearchNavTab) => {
const mapState = makeMapStateToProps(); const mapState = makeMapStateToProps();
const { urlState } = useSelector(mapState, isEqual); const { urlState } = useDeepEqualSelector(mapState);
const urlSearch = useMemo(() => getSearch(tab, urlState), [tab, urlState]); const urlSearch = useMemo(() => getSearch(tab, urlState), [tab, urlState]);
return urlSearch; return urlSearch;
}; };

View file

@ -8,7 +8,7 @@ import { set } from '@elastic/safer-lodash-set/fp';
import { keyBy, pick, isEmpty, isEqual, isUndefined } from 'lodash/fp'; import { keyBy, pick, isEmpty, isEqual, isUndefined } from 'lodash/fp';
import memoizeOne from 'memoize-one'; import memoizeOne from 'memoize-one';
import { useCallback, useEffect, useMemo, useRef, useState } from 'react'; import { useCallback, useEffect, useMemo, useRef, useState } from 'react';
import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { useDispatch } from 'react-redux';
import { IIndexPattern } from 'src/plugins/data/public'; import { IIndexPattern } from 'src/plugins/data/public';
import { useKibana } from '../../lib/kibana'; import { useKibana } from '../../lib/kibana';
@ -20,11 +20,10 @@ import {
BrowserFields, BrowserFields,
} from '../../../../common/search_strategy/index_fields'; } from '../../../../common/search_strategy/index_fields';
import { AbortError } from '../../../../../../../src/plugins/data/common'; import { AbortError } from '../../../../../../../src/plugins/data/common';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import * as i18n from './translations'; import * as i18n from './translations';
import { SourcererScopeName } from '../../store/sourcerer/model'; import { SourcererScopeName } from '../../store/sourcerer/model';
import { sourcererActions, sourcererSelectors } from '../../store/sourcerer'; import { sourcererActions, sourcererSelectors } from '../../store/sourcerer';
import { State } from '../../store';
import { DocValueFields } from '../../../../common/search_strategy/common'; import { DocValueFields } from '../../../../common/search_strategy/common';
export { BrowserField, BrowserFields, DocValueFields }; export { BrowserField, BrowserFields, DocValueFields };
@ -201,9 +200,8 @@ export const useIndexFields = (sourcererScopeName: SourcererScopeName) => {
() => sourcererSelectors.getIndexNamesSelectedSelector(), () => sourcererSelectors.getIndexNamesSelectedSelector(),
[] []
); );
const indexNames = useSelector<State, string[]>( const indexNames = useShallowEqualSelector<string[]>((state) =>
(state) => indexNamesSelectedSelector(state, sourcererScopeName), indexNamesSelectedSelector(state, sourcererScopeName)
shallowEqual
); );
const setLoading = useCallback( const setLoading = useCallback(

View file

@ -5,9 +5,10 @@
*/ */
import { useCallback, useMemo } from 'react'; import { useCallback, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch } from 'react-redux';
import { SCROLLING_DISABLED_CLASS_NAME } from '../../../../common/constants';
import { SCROLLING_DISABLED_CLASS_NAME } from '../../../../common/constants';
import { useShallowEqualSelector } from '../../hooks/use_selector';
import { inputsSelectors } from '../../store'; import { inputsSelectors } from '../../store';
import { inputsActions } from '../../store/actions'; import { inputsActions } from '../../store/actions';
@ -29,8 +30,10 @@ export const resetScroll = () => {
export const useFullScreen = () => { export const useFullScreen = () => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const globalFullScreen = useSelector(inputsSelectors.globalFullScreenSelector) ?? false; const globalFullScreen =
const timelineFullScreen = useSelector(inputsSelectors.timelineFullScreenSelector) ?? false; useShallowEqualSelector(inputsSelectors.globalFullScreenSelector) ?? false;
const timelineFullScreen =
useShallowEqualSelector(inputsSelectors.timelineFullScreenSelector) ?? false;
const setGlobalFullScreen = useCallback( const setGlobalFullScreen = useCallback(
(fullScreen: boolean) => { (fullScreen: boolean) => {

View file

@ -5,15 +5,16 @@
*/ */
import { useCallback, useState, useEffect, useMemo } from 'react'; import { useCallback, useState, useEffect, useMemo } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useShallowEqualSelector } from '../../hooks/use_selector';
import { inputsSelectors } from '../../store'; import { inputsSelectors } from '../../store';
import { inputsActions } from '../../store/actions'; import { inputsActions } from '../../store/actions';
import { SetQuery, DeleteQuery } from './types'; import { SetQuery, DeleteQuery } from './types';
export const useGlobalTime = (clearAllQuery: boolean = true) => { export const useGlobalTime = (clearAllQuery: boolean = true) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { from, to } = useSelector(inputsSelectors.globalTimeRangeSelector); const { from, to } = useShallowEqualSelector(inputsSelectors.globalTimeRangeSelector);
const [isInitializing, setIsInitializing] = useState(true); const [isInitializing, setIsInitializing] = useState(true);
const setQuery = useCallback( const setQuery = useCallback(

View file

@ -0,0 +1,20 @@
/*
* Copyright Elasticsearch B.V. and/or licensed to Elasticsearch B.V. under one
* or more contributor license agreements. Licensed under the Elastic License;
* you may not use this file except in compliance with the Elastic License.
*/
import { shallowEqual, useSelector } from 'react-redux';
import deepEqual from 'fast-deep-equal';
import { State } from '../store';
export type TypedUseSelectorHook = <TSelected, TState = State>(
selector: (state: TState) => TSelected,
equalityFn?: (left: TSelected, right: TSelected) => boolean
) => TSelected;
export const useShallowEqualSelector: TypedUseSelectorHook = (selector) =>
useSelector(selector, shallowEqual);
export const useDeepEqualSelector: TypedUseSelectorHook = (selector) =>
useSelector(selector, deepEqual);

View file

@ -6,7 +6,6 @@
import { noop } from 'lodash/fp'; import { noop } from 'lodash/fp';
import { useCallback, useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { shallowEqual, useSelector } from 'react-redux';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { import {
@ -26,7 +25,8 @@ import {
} from '../../../../common/search_strategy'; } from '../../../../common/search_strategy';
import { ESTermQuery } from '../../../../common/typed_json'; import { ESTermQuery } from '../../../../common/typed_json';
import { inputsModel, State } from '../../../common/store'; import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { inputsModel } from '../../../common/store';
import { createFilter } from '../../../common/containers/helpers'; import { createFilter } from '../../../common/containers/helpers';
import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers'; import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers';
import { useKibana } from '../../../common/lib/kibana'; import { useKibana } from '../../../common/lib/kibana';
@ -71,9 +71,8 @@ export const useAuthentications = ({
skip, skip,
}: UseAuthentications): [boolean, AuthenticationArgs] => { }: UseAuthentications): [boolean, AuthenticationArgs] => {
const getAuthenticationsSelector = hostsSelectors.authenticationsSelector(); const getAuthenticationsSelector = hostsSelectors.authenticationsSelector();
const { activePage, limit } = useSelector( const { activePage, limit } = useShallowEqualSelector((state) =>
(state: State) => getAuthenticationsSelector(state, type), getAuthenticationsSelector(state, type)
shallowEqual
); );
const { data, notifications } = useKibana().services; const { data, notifications } = useKibana().services;
const refetch = useRef<inputsModel.Refetch>(noop); const refetch = useRef<inputsModel.Refetch>(noop);

View file

@ -7,11 +7,11 @@
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { noop } from 'lodash/fp'; import { noop } from 'lodash/fp';
import { useCallback, useEffect, useRef, useState } from 'react'; import { useCallback, useEffect, useRef, useState } from 'react';
import { useSelector } from 'react-redux';
import { inputsModel, State } from '../../../common/store'; import { inputsModel, State } from '../../../common/store';
import { createFilter } from '../../../common/containers/helpers'; import { createFilter } from '../../../common/containers/helpers';
import { useKibana } from '../../../common/lib/kibana'; import { useKibana } from '../../../common/lib/kibana';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { hostsModel, hostsSelectors } from '../../store'; import { hostsModel, hostsSelectors } from '../../store';
import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers'; import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers';
import { import {
@ -69,7 +69,7 @@ export const useAllHost = ({
type, type,
}: UseAllHost): [boolean, HostsArgs] => { }: UseAllHost): [boolean, HostsArgs] => {
const getHostsSelector = hostsSelectors.hostsSelector(); const getHostsSelector = hostsSelectors.hostsSelector();
const { activePage, direction, limit, sortField } = useSelector((state: State) => const { activePage, direction, limit, sortField } = useShallowEqualSelector((state: State) =>
getHostsSelector(state, type) getHostsSelector(state, type)
); );
const { data, notifications } = useKibana().services; const { data, notifications } = useKibana().services;

View file

@ -5,7 +5,7 @@
*/ */
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { useDispatch } from 'react-redux';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { networkActions, networkModel, networkSelectors } from '../../store'; import { networkActions, networkModel, networkSelectors } from '../../store';
@ -16,6 +16,7 @@ import {
NetworkDnsFields, NetworkDnsFields,
} from '../../../../common/search_strategy'; } from '../../../../common/search_strategy';
import { Criteria, ItemsPerRow, PaginatedTable } from '../../../common/components/paginated_table'; import { Criteria, ItemsPerRow, PaginatedTable } from '../../../common/components/paginated_table';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { getNetworkDnsColumns } from './columns'; import { getNetworkDnsColumns } from './columns';
import { IsPtrIncluded } from './is_ptr_included'; import { IsPtrIncluded } from './is_ptr_included';
@ -59,10 +60,7 @@ const NetworkDnsTableComponent: React.FC<NetworkDnsTableProps> = ({
}) => { }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const getNetworkDnsSelector = networkSelectors.dnsSelector(); const getNetworkDnsSelector = networkSelectors.dnsSelector();
const { activePage, isPtrIncluded, limit, sort } = useSelector( const { activePage, isPtrIncluded, limit, sort } = useShallowEqualSelector(getNetworkDnsSelector);
getNetworkDnsSelector,
shallowEqual
);
const updateLimitPagination = useCallback( const updateLimitPagination = useCallback(
(newLimit) => (newLimit) =>
dispatch( dispatch(

View file

@ -5,11 +5,11 @@
*/ */
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { useDispatch } from 'react-redux';
import { networkActions, networkModel, networkSelectors } from '../../store'; import { networkActions, networkModel, networkSelectors } from '../../store';
import { NetworkHttpEdges, NetworkHttpFields } from '../../../../common/search_strategy'; import { NetworkHttpEdges, NetworkHttpFields } from '../../../../common/search_strategy';
import { State } from '../../../common/store'; import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { Criteria, ItemsPerRow, PaginatedTable } from '../../../common/components/paginated_table'; import { Criteria, ItemsPerRow, PaginatedTable } from '../../../common/components/paginated_table';
import { getNetworkHttpColumns } from './columns'; import { getNetworkHttpColumns } from './columns';
@ -51,9 +51,8 @@ const NetworkHttpTableComponent: React.FC<NetworkHttpTableProps> = ({
}) => { }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const getNetworkHttpSelector = networkSelectors.httpSelector(); const getNetworkHttpSelector = networkSelectors.httpSelector();
const { activePage, limit, sort } = useSelector( const { activePage, limit, sort } = useShallowEqualSelector((state) =>
(state: State) => getNetworkHttpSelector(state, type), getNetworkHttpSelector(state, type)
shallowEqual
); );
const tableType = const tableType =
type === networkModel.NetworkType.page type === networkModel.NetworkType.page

View file

@ -6,7 +6,7 @@
import { last } from 'lodash/fp'; import { last } from 'lodash/fp';
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { useDispatch } from 'react-redux';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { IIndexPattern } from 'src/plugins/data/public'; import { IIndexPattern } from 'src/plugins/data/public';
@ -18,7 +18,7 @@ import {
NetworkTopTablesFields, NetworkTopTablesFields,
SortField, SortField,
} from '../../../../common/search_strategy'; } from '../../../../common/search_strategy';
import { State } from '../../../common/store'; import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { Criteria, ItemsPerRow, PaginatedTable } from '../../../common/components/paginated_table'; import { Criteria, ItemsPerRow, PaginatedTable } from '../../../common/components/paginated_table';
@ -67,9 +67,8 @@ const NetworkTopCountriesTableComponent: React.FC<NetworkTopCountriesTableProps>
}) => { }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const getTopCountriesSelector = networkSelectors.topCountriesSelector(); const getTopCountriesSelector = networkSelectors.topCountriesSelector();
const { activePage, limit, sort } = useSelector( const { activePage, limit, sort } = useShallowEqualSelector((state) =>
(state: State) => getTopCountriesSelector(state, type, flowTargeted), getTopCountriesSelector(state, type, flowTargeted)
shallowEqual
); );
const headerTitle: string = useMemo( const headerTitle: string = useMemo(

View file

@ -5,7 +5,7 @@
*/ */
import { last } from 'lodash/fp'; import { last } from 'lodash/fp';
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { useDispatch } from 'react-redux';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { import {
@ -15,7 +15,7 @@ import {
NetworkTopNFlowEdges, NetworkTopNFlowEdges,
NetworkTopTablesFields, NetworkTopTablesFields,
} from '../../../../common/search_strategy'; } from '../../../../common/search_strategy';
import { State } from '../../../common/store'; import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { Criteria, ItemsPerRow, PaginatedTable } from '../../../common/components/paginated_table'; import { Criteria, ItemsPerRow, PaginatedTable } from '../../../common/components/paginated_table';
import { networkActions, networkModel, networkSelectors } from '../../store'; import { networkActions, networkModel, networkSelectors } from '../../store';
import { getNFlowColumnsCurated } from './columns'; import { getNFlowColumnsCurated } from './columns';
@ -61,9 +61,8 @@ const NetworkTopNFlowTableComponent: React.FC<NetworkTopNFlowTableProps> = ({
}) => { }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const getTopNFlowSelector = networkSelectors.topNFlowSelector(); const getTopNFlowSelector = networkSelectors.topNFlowSelector();
const { activePage, limit, sort } = useSelector( const { activePage, limit, sort } = useShallowEqualSelector((state) =>
(state: State) => getTopNFlowSelector(state, type, flowTargeted), getTopNFlowSelector(state, type, flowTargeted)
shallowEqual
); );
const columns = useMemo( const columns = useMemo(

View file

@ -5,7 +5,7 @@
*/ */
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { useDispatch } from 'react-redux';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { networkActions, networkModel, networkSelectors } from '../../store'; import { networkActions, networkModel, networkSelectors } from '../../store';
@ -15,7 +15,7 @@ import {
NetworkTlsFields, NetworkTlsFields,
SortField, SortField,
} from '../../../../common/search_strategy'; } from '../../../../common/search_strategy';
import { State } from '../../../common/store'; import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { import {
Criteria, Criteria,
ItemsPerRow, ItemsPerRow,
@ -63,9 +63,8 @@ const TlsTableComponent: React.FC<TlsTableProps> = ({
}) => { }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const getTlsSelector = networkSelectors.tlsSelector(); const getTlsSelector = networkSelectors.tlsSelector();
const { activePage, limit, sort } = useSelector( const { activePage, limit, sort } = useShallowEqualSelector((state) =>
(state: State) => getTlsSelector(state, type), getTlsSelector(state, type)
shallowEqual
); );
const tableType: networkModel.TopTlsTableType = const tableType: networkModel.TopTlsTableType =
type === networkModel.NetworkType.page type === networkModel.NetworkType.page

View file

@ -5,9 +5,10 @@
*/ */
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { useDispatch } from 'react-redux';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { assertUnreachable } from '../../../../common/utility_types'; import { assertUnreachable } from '../../../../common/utility_types';
import { networkActions, networkModel, networkSelectors } from '../../store'; import { networkActions, networkModel, networkSelectors } from '../../store';
import { import {
@ -68,7 +69,7 @@ const UsersTableComponent: React.FC<UsersTableProps> = ({
}) => { }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const getUsersSelector = networkSelectors.usersSelector(); const getUsersSelector = networkSelectors.usersSelector();
const { activePage, sort, limit } = useSelector(getUsersSelector, shallowEqual); const { activePage, sort, limit } = useShallowEqualSelector(getUsersSelector);
const updateLimitPagination = useCallback( const updateLimitPagination = useCallback(
(newLimit) => (newLimit) =>
dispatch( dispatch(

View file

@ -6,11 +6,11 @@
import { noop } from 'lodash/fp'; import { noop } from 'lodash/fp';
import { useState, useEffect, useCallback, useRef } from 'react'; import { useState, useEffect, useCallback, useRef } from 'react';
import { shallowEqual, useSelector } from 'react-redux';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { ESTermQuery } from '../../../../common/typed_json'; import { ESTermQuery } from '../../../../common/typed_json';
import { inputsModel, State } from '../../../common/store'; import { inputsModel } from '../../../common/store';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { useKibana } from '../../../common/lib/kibana'; import { useKibana } from '../../../common/lib/kibana';
import { createFilter } from '../../../common/containers/helpers'; import { createFilter } from '../../../common/containers/helpers';
import { NetworkDnsEdges, PageInfoPaginated } from '../../../../common/search_strategy'; import { NetworkDnsEdges, PageInfoPaginated } from '../../../../common/search_strategy';
@ -68,10 +68,7 @@ export const useNetworkDns = ({
type, type,
}: UseNetworkDns): [boolean, NetworkDnsArgs] => { }: UseNetworkDns): [boolean, NetworkDnsArgs] => {
const getNetworkDnsSelector = networkSelectors.dnsSelector(); const getNetworkDnsSelector = networkSelectors.dnsSelector();
const { activePage, sort, isPtrIncluded, limit } = useSelector( const { activePage, sort, isPtrIncluded, limit } = useShallowEqualSelector(getNetworkDnsSelector);
(state: State) => getNetworkDnsSelector(state),
shallowEqual
);
const { data, notifications } = useKibana().services; const { data, notifications } = useKibana().services;
const refetch = useRef<inputsModel.Refetch>(noop); const refetch = useRef<inputsModel.Refetch>(noop);
const abortCtrl = useRef(new AbortController()); const abortCtrl = useRef(new AbortController());

View file

@ -6,11 +6,11 @@
import { noop } from 'lodash/fp'; import { noop } from 'lodash/fp';
import { useState, useEffect, useCallback, useRef } from 'react'; import { useState, useEffect, useCallback, useRef } from 'react';
import { shallowEqual, useSelector } from 'react-redux';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { ESTermQuery } from '../../../../common/typed_json'; import { ESTermQuery } from '../../../../common/typed_json';
import { inputsModel, State } from '../../../common/store'; import { inputsModel } from '../../../common/store';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { useKibana } from '../../../common/lib/kibana'; import { useKibana } from '../../../common/lib/kibana';
import { createFilter } from '../../../common/containers/helpers'; import { createFilter } from '../../../common/containers/helpers';
import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers'; import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers';
@ -68,9 +68,8 @@ export const useNetworkHttp = ({
type, type,
}: UseNetworkHttp): [boolean, NetworkHttpArgs] => { }: UseNetworkHttp): [boolean, NetworkHttpArgs] => {
const getHttpSelector = networkSelectors.httpSelector(); const getHttpSelector = networkSelectors.httpSelector();
const { activePage, limit, sort } = useSelector( const { activePage, limit, sort } = useShallowEqualSelector((state) =>
(state: State) => getHttpSelector(state, type), getHttpSelector(state, type)
shallowEqual
); );
const { data, notifications } = useKibana().services; const { data, notifications } = useKibana().services;
const refetch = useRef<inputsModel.Refetch>(noop); const refetch = useRef<inputsModel.Refetch>(noop);

View file

@ -6,11 +6,11 @@
import { noop } from 'lodash/fp'; import { noop } from 'lodash/fp';
import { useState, useEffect, useCallback, useRef } from 'react'; import { useState, useEffect, useCallback, useRef } from 'react';
import { shallowEqual, useSelector } from 'react-redux';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { ESTermQuery } from '../../../../common/typed_json'; import { ESTermQuery } from '../../../../common/typed_json';
import { inputsModel, State } from '../../../common/store'; import { inputsModel } from '../../../common/store';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { useKibana } from '../../../common/lib/kibana'; import { useKibana } from '../../../common/lib/kibana';
import { createFilter } from '../../../common/containers/helpers'; import { createFilter } from '../../../common/containers/helpers';
import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers'; import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers';
@ -66,9 +66,8 @@ export const useNetworkTopCountries = ({
type, type,
}: UseNetworkTopCountries): [boolean, NetworkTopCountriesArgs] => { }: UseNetworkTopCountries): [boolean, NetworkTopCountriesArgs] => {
const getTopCountriesSelector = networkSelectors.topCountriesSelector(); const getTopCountriesSelector = networkSelectors.topCountriesSelector();
const { activePage, limit, sort } = useSelector( const { activePage, limit, sort } = useShallowEqualSelector((state) =>
(state: State) => getTopCountriesSelector(state, type, flowTarget), getTopCountriesSelector(state, type, flowTarget)
shallowEqual
); );
const { data, notifications } = useKibana().services; const { data, notifications } = useKibana().services;
const refetch = useRef<inputsModel.Refetch>(noop); const refetch = useRef<inputsModel.Refetch>(noop);

View file

@ -6,11 +6,11 @@
import { noop } from 'lodash/fp'; import { noop } from 'lodash/fp';
import { useState, useEffect, useCallback, useRef } from 'react'; import { useState, useEffect, useCallback, useRef } from 'react';
import { shallowEqual, useSelector } from 'react-redux';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { ESTermQuery } from '../../../../common/typed_json'; import { ESTermQuery } from '../../../../common/typed_json';
import { inputsModel, State } from '../../../common/store'; import { inputsModel } from '../../../common/store';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { useKibana } from '../../../common/lib/kibana'; import { useKibana } from '../../../common/lib/kibana';
import { createFilter } from '../../../common/containers/helpers'; import { createFilter } from '../../../common/containers/helpers';
import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers'; import { generateTablePaginationOptions } from '../../../common/components/paginated_table/helpers';
@ -66,9 +66,8 @@ export const useNetworkTopNFlow = ({
type, type,
}: UseNetworkTopNFlow): [boolean, NetworkTopNFlowArgs] => { }: UseNetworkTopNFlow): [boolean, NetworkTopNFlowArgs] => {
const getTopNFlowSelector = networkSelectors.topNFlowSelector(); const getTopNFlowSelector = networkSelectors.topNFlowSelector();
const { activePage, limit, sort } = useSelector( const { activePage, limit, sort } = useShallowEqualSelector((state) =>
(state: State) => getTopNFlowSelector(state, type, flowTarget), getTopNFlowSelector(state, type, flowTarget)
shallowEqual
); );
const { data, notifications } = useKibana().services; const { data, notifications } = useKibana().services;
const refetch = useRef<inputsModel.Refetch>(noop); const refetch = useRef<inputsModel.Refetch>(noop);

View file

@ -6,11 +6,11 @@
import { noop } from 'lodash/fp'; import { noop } from 'lodash/fp';
import { useState, useEffect, useCallback, useRef } from 'react'; import { useState, useEffect, useCallback, useRef } from 'react';
import { shallowEqual, useSelector } from 'react-redux';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { ESTermQuery } from '../../../../common/typed_json'; import { ESTermQuery } from '../../../../common/typed_json';
import { inputsModel, State } from '../../../common/store'; import { inputsModel } from '../../../common/store';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { useKibana } from '../../../common/lib/kibana'; import { useKibana } from '../../../common/lib/kibana';
import { createFilter } from '../../../common/containers/helpers'; import { createFilter } from '../../../common/containers/helpers';
import { PageInfoPaginated, FlowTargetSourceDest } from '../../../graphql/types'; import { PageInfoPaginated, FlowTargetSourceDest } from '../../../graphql/types';
@ -67,9 +67,8 @@ export const useNetworkTls = ({
type, type,
}: UseNetworkTls): [boolean, NetworkTlsArgs] => { }: UseNetworkTls): [boolean, NetworkTlsArgs] => {
const getTlsSelector = networkSelectors.tlsSelector(); const getTlsSelector = networkSelectors.tlsSelector();
const { activePage, limit, sort } = useSelector( const { activePage, limit, sort } = useShallowEqualSelector((state) =>
(state: State) => getTlsSelector(state, type, flowTarget), getTlsSelector(state, type, flowTarget)
shallowEqual
); );
const { data, notifications } = useKibana().services; const { data, notifications } = useKibana().services;
const refetch = useRef<inputsModel.Refetch>(noop); const refetch = useRef<inputsModel.Refetch>(noop);

View file

@ -6,9 +6,9 @@
import { noop } from 'lodash/fp'; import { noop } from 'lodash/fp';
import { useState, useEffect, useCallback, useRef } from 'react'; import { useState, useEffect, useCallback, useRef } from 'react';
import { shallowEqual, useSelector } from 'react-redux';
import deepEqual from 'fast-deep-equal'; import deepEqual from 'fast-deep-equal';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { ESTermQuery } from '../../../../common/typed_json'; import { ESTermQuery } from '../../../../common/typed_json';
import { DEFAULT_INDEX_KEY } from '../../../../common/constants'; import { DEFAULT_INDEX_KEY } from '../../../../common/constants';
import { inputsModel } from '../../../common/store'; import { inputsModel } from '../../../common/store';
@ -66,7 +66,7 @@ export const useNetworkUsers = ({
startDate, startDate,
}: UseNetworkUsers): [boolean, NetworkUsersArgs] => { }: UseNetworkUsers): [boolean, NetworkUsersArgs] => {
const getNetworkUsersSelector = networkSelectors.usersSelector(); const getNetworkUsersSelector = networkSelectors.usersSelector();
const { activePage, sort, limit } = useSelector(getNetworkUsersSelector, shallowEqual); const { activePage, sort, limit } = useShallowEqualSelector(getNetworkUsersSelector);
const { data, notifications, uiSettings } = useKibana().services; const { data, notifications, uiSettings } = useKibana().services;
const refetch = useRef<inputsModel.Refetch>(noop); const refetch = useRef<inputsModel.Refetch>(noop);
const abortCtrl = useRef(new AbortController()); const abortCtrl = useRef(new AbortController());

View file

@ -6,9 +6,10 @@
import { EuiHorizontalRule, EuiSpacer, EuiFlexItem } from '@elastic/eui'; import { EuiHorizontalRule, EuiSpacer, EuiFlexItem } from '@elastic/eui';
import React, { useCallback, useEffect, useMemo } from 'react'; import React, { useCallback, useEffect, useMemo } from 'react';
import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useParams } from 'react-router-dom'; import { useParams } from 'react-router-dom';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { FlowTarget, LastEventIndexKey } from '../../../../common/search_strategy'; import { FlowTarget, LastEventIndexKey } from '../../../../common/search_strategy';
import { useGlobalTime } from '../../../common/containers/use_global_time'; import { useGlobalTime } from '../../../common/containers/use_global_time';
import { FiltersGlobal } from '../../../common/components/filters_global'; import { FiltersGlobal } from '../../../common/components/filters_global';
@ -58,8 +59,8 @@ const NetworkDetailsComponent: React.FC = () => {
const getGlobalQuerySelector = inputsSelectors.globalQuerySelector(); const getGlobalQuerySelector = inputsSelectors.globalQuerySelector();
const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector(); const getGlobalFiltersQuerySelector = inputsSelectors.globalFiltersQuerySelector();
const query = useSelector(getGlobalQuerySelector, shallowEqual); const query = useShallowEqualSelector(getGlobalQuerySelector);
const filters = useSelector(getGlobalFiltersQuerySelector, shallowEqual); const filters = useShallowEqualSelector(getGlobalFiltersQuerySelector);
const type = networkModel.NetworkType.details; const type = networkModel.NetworkType.details;
const narrowDateRange = useCallback( const narrowDateRange = useCallback(

View file

@ -14,7 +14,7 @@ import {
} from '@elastic/eui'; } from '@elastic/eui';
import { noop } from 'lodash/fp'; import { noop } from 'lodash/fp';
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import { connect, ConnectedProps, useDispatch, useSelector } from 'react-redux'; import { connect, ConnectedProps, useDispatch } from 'react-redux';
import styled from 'styled-components'; import styled from 'styled-components';
import { FULL_SCREEN } from '../timeline/body/column_headers/translations'; import { FULL_SCREEN } from '../timeline/body/column_headers/translations';
@ -22,6 +22,7 @@ import { EXIT_FULL_SCREEN } from '../../../common/components/exit_full_screen/tr
import { DEFAULT_INDEX_KEY, FULL_SCREEN_TOGGLED_CLASS_NAME } from '../../../../common/constants'; import { DEFAULT_INDEX_KEY, FULL_SCREEN_TOGGLED_CLASS_NAME } from '../../../../common/constants';
import { useFullScreen } from '../../../common/containers/use_full_screen'; import { useFullScreen } from '../../../common/containers/use_full_screen';
import { State } from '../../../common/store'; import { State } from '../../../common/store';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { TimelineId, TimelineType } from '../../../../common/types/timeline'; import { TimelineId, TimelineType } from '../../../../common/types/timeline';
import { timelineSelectors } from '../../store/timeline'; import { timelineSelectors } from '../../store/timeline';
import { timelineDefaults } from '../../store/timeline/defaults'; import { timelineDefaults } from '../../store/timeline/defaults';
@ -109,7 +110,7 @@ const GraphOverlayComponent = ({
dispatch(updateTimelineGraphEventId({ id: timelineId, graphEventId: '' })); dispatch(updateTimelineGraphEventId({ id: timelineId, graphEventId: '' }));
}, [dispatch, timelineId]); }, [dispatch, timelineId]);
const currentTimeline = useSelector((state: State) => const currentTimeline = useShallowEqualSelector((state) =>
timelineSelectors.selectTimeline(state, timelineId) timelineSelectors.selectTimeline(state, timelineId)
); );

View file

@ -6,11 +6,12 @@
import ApolloClient from 'apollo-client'; import ApolloClient from 'apollo-client';
import React, { useEffect, useState, useCallback, useMemo } from 'react'; import React, { useEffect, useState, useCallback, useMemo } from 'react';
import { connect, ConnectedProps, shallowEqual, useSelector } from 'react-redux'; import { connect, ConnectedProps } from 'react-redux';
import { Dispatch } from 'redux'; import { Dispatch } from 'redux';
import { DeleteTimelineMutation, SortFieldTimeline, Direction } from '../../../graphql/types'; import { DeleteTimelineMutation, SortFieldTimeline, Direction } from '../../../graphql/types';
import { sourcererSelectors, State } from '../../../common/store'; import { sourcererSelectors, State } from '../../../common/store';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { TimelineId } from '../../../../common/types/timeline'; import { TimelineId } from '../../../../common/types/timeline';
import { ColumnHeaderOptions, TimelineModel } from '../../../timelines/store/timeline/model'; import { ColumnHeaderOptions, TimelineModel } from '../../../timelines/store/timeline/model';
import { timelineSelectors } from '../../../timelines/store/timeline'; import { timelineSelectors } from '../../../timelines/store/timeline';
@ -114,10 +115,7 @@ export const StatefulOpenTimelineComponent = React.memo<OpenTimelineOwnProps>(
() => sourcererSelectors.getAllExistingIndexNamesSelector(), () => sourcererSelectors.getAllExistingIndexNamesSelector(),
[] []
); );
const existingIndexNames = useSelector<State, string[]>( const existingIndexNames = useShallowEqualSelector<string[]>(existingIndexNamesSelector);
existingIndexNamesSelector,
shallowEqual
);
const { const {
customTemplateTimelineCount, customTemplateTimelineCount,

View file

@ -20,10 +20,11 @@ import {
EuiInMemoryTable, EuiInMemoryTable,
} from '@elastic/eui'; } from '@elastic/eui';
import React, { useState, useCallback, useRef } from 'react'; import React, { useState, useCallback, useRef } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch } from 'react-redux';
import styled from 'styled-components'; import styled from 'styled-components';
import { State } from '../../../common/store'; import { State } from '../../../common/store';
import { useShallowEqualSelector } from '../../../common/hooks/use_selector';
import { renderers } from './catalog'; import { renderers } from './catalog';
import { setExcludedRowRendererIds as dispatchSetExcludedRowRendererIds } from '../../../timelines/store/timeline/actions'; import { setExcludedRowRendererIds as dispatchSetExcludedRowRendererIds } from '../../../timelines/store/timeline/actions';
@ -81,7 +82,7 @@ const StatefulRowRenderersBrowserComponent: React.FC<StatefulRowRenderersBrowser
}) => { }) => {
const tableRef = useRef<EuiInMemoryTable<{}>>(); const tableRef = useRef<EuiInMemoryTable<{}>>();
const dispatch = useDispatch(); const dispatch = useDispatch();
const excludedRowRendererIds = useSelector( const excludedRowRendererIds = useShallowEqualSelector(
(state: State) => state.timeline.timelineById[timelineId]?.excludedRowRendererIds || [] (state: State) => state.timeline.timelineById[timelineId]?.excludedRowRendererIds || []
); );
const [show, setShow] = useState(false); const [show, setShow] = useState(false);

View file

@ -5,22 +5,20 @@
*/ */
import { mount } from 'enzyme'; import { mount } from 'enzyme';
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux';
import { TestProviders, mockTimelineModel } from '../../../../../common/mock'; import { TestProviders, mockTimelineModel } from '../../../../../common/mock';
import { DEFAULT_ACTIONS_COLUMN_WIDTH } from '../constants'; import { DEFAULT_ACTIONS_COLUMN_WIDTH } from '../constants';
import { Actions } from '.'; import { Actions } from '.';
import { useShallowEqualSelector } from '../../../../../common/hooks/use_selector';
jest.mock('react-redux', () => { jest.mock('../../../../../common/hooks/use_selector', () => ({
const origin = jest.requireActual('react-redux'); useShallowEqualSelector: jest.fn(),
return { }));
...origin,
useSelector: jest.fn(),
};
});
describe('Actions', () => { describe('Actions', () => {
(useSelector as jest.Mock).mockReturnValue(mockTimelineModel); beforeEach(() => {
(useShallowEqualSelector as jest.Mock).mockReturnValue(mockTimelineModel);
});
test('it renders a checkbox for selecting the event when `showCheckboxes` is `true`', () => { test('it renders a checkbox for selecting the event when `showCheckboxes` is `true`', () => {
const wrapper = mount( const wrapper = mount(

View file

@ -6,8 +6,8 @@
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import uuid from 'uuid'; import uuid from 'uuid';
import { useSelector, shallowEqual } from 'react-redux';
import { useShallowEqualSelector } from '../../../../../common/hooks/use_selector';
import { Ecs } from '../../../../../../common/ecs'; import { Ecs } from '../../../../../../common/ecs';
import { TimelineNonEcsData } from '../../../../../../common/search_strategy/timeline'; import { TimelineNonEcsData } from '../../../../../../common/search_strategy/timeline';
import { Note } from '../../../../../common/lib/note'; import { Note } from '../../../../../common/lib/note';
@ -28,7 +28,6 @@ import { AlertContextMenu } from '../../../../../detections/components/alerts_ta
import { InvestigateInTimelineAction } from '../../../../../detections/components/alerts_table/timeline_actions/investigate_in_timeline_action'; import { InvestigateInTimelineAction } from '../../../../../detections/components/alerts_table/timeline_actions/investigate_in_timeline_action';
import { AddEventNoteAction } from '../actions/add_note_icon_item'; import { AddEventNoteAction } from '../actions/add_note_icon_item';
import { PinEventAction } from '../actions/pin_event_action'; import { PinEventAction } from '../actions/pin_event_action';
import { StoreState } from '../../../../../common/store/types';
import { inputsModel } from '../../../../../common/store'; import { inputsModel } from '../../../../../common/store';
import { TimelineId } from '../../../../../../common/types/timeline'; import { TimelineId } from '../../../../../../common/types/timeline';
@ -96,9 +95,8 @@ export const EventColumnView = React.memo<Props>(
toggleShowNotes, toggleShowNotes,
updateNote, updateNote,
}) => { }) => {
const { timelineType, status } = useSelector<StoreState, TimelineModel>( const { timelineType, status } = useShallowEqualSelector<TimelineModel>(
(state) => state.timeline.timelineById[timelineId], (state) => state.timeline.timelineById[timelineId]
shallowEqual
); );
const handlePinClicked = useCallback( const handlePinClicked = useCallback(

View file

@ -5,11 +5,11 @@
*/ */
import React, { useRef, useState, useCallback } from 'react'; import React, { useRef, useState, useCallback } from 'react';
import { useSelector } from 'react-redux';
import uuid from 'uuid'; import uuid from 'uuid';
import VisibilitySensor from 'react-visibility-sensor'; import VisibilitySensor from 'react-visibility-sensor';
import { BrowserFields, DocValueFields } from '../../../../../common/containers/source'; import { BrowserFields, DocValueFields } from '../../../../../common/containers/source';
import { useShallowEqualSelector } from '../../../../../common/hooks/use_selector';
import { useTimelineEventsDetails } from '../../../../containers/details'; import { useTimelineEventsDetails } from '../../../../containers/details';
import { import {
TimelineEventsDetailsItem, TimelineEventsDetailsItem,
@ -37,7 +37,7 @@ import { getEventType } from '../helpers';
import { NoteCards } from '../../../notes/note_cards'; import { NoteCards } from '../../../notes/note_cards';
import { useEventDetailsWidthContext } from '../../../../../common/components/events_viewer/event_details_width_context'; import { useEventDetailsWidthContext } from '../../../../../common/components/events_viewer/event_details_width_context';
import { EventColumnView } from './event_column_view'; import { EventColumnView } from './event_column_view';
import { inputsModel, StoreState } from '../../../../../common/store'; import { inputsModel } from '../../../../../common/store';
interface Props { interface Props {
actionsColumnWidth: number; actionsColumnWidth: number;
@ -136,7 +136,7 @@ const StatefulEventComponent: React.FC<Props> = ({
}) => { }) => {
const [expanded, setExpanded] = useState<{ [eventId: string]: boolean }>({}); const [expanded, setExpanded] = useState<{ [eventId: string]: boolean }>({});
const [showNotes, setShowNotes] = useState<{ [eventId: string]: boolean }>({}); const [showNotes, setShowNotes] = useState<{ [eventId: string]: boolean }>({});
const { status: timelineStatus } = useSelector<StoreState, TimelineModel>( const { status: timelineStatus } = useShallowEqualSelector<TimelineModel>(
(state) => state.timeline.timelineById[timelineId] (state) => state.timeline.timelineById[timelineId]
); );
const divElement = useRef<HTMLDivElement | null>(null); const divElement = useRef<HTMLDivElement | null>(null);

View file

@ -5,7 +5,6 @@
*/ */
import { ReactWrapper } from 'enzyme'; import { ReactWrapper } from 'enzyme';
import React from 'react'; import React from 'react';
import { useSelector } from 'react-redux';
import '../../../../common/mock/match_media'; import '../../../../common/mock/match_media';
import { mockBrowserFields } from '../../../../common/containers/source/mock'; import { mockBrowserFields } from '../../../../common/containers/source/mock';
@ -28,13 +27,9 @@ const mockSort: Sort = {
sortDirection: Direction.desc, sortDirection: Direction.desc,
}; };
jest.mock('react-redux', () => { jest.mock('../../../../common/hooks/use_selector', () => ({
const origin = jest.requireActual('react-redux'); useShallowEqualSelector: jest.fn().mockReturnValue(mockTimelineModel),
return { }));
...origin,
useSelector: jest.fn(),
};
});
jest.mock('../../../../common/components/link_to'); jest.mock('../../../../common/components/link_to');
@ -87,7 +82,6 @@ describe('Body', () => {
toggleColumn: jest.fn(), toggleColumn: jest.fn(),
updateNote: jest.fn(), updateNote: jest.fn(),
}; };
(useSelector as jest.Mock).mockReturnValue(mockTimelineModel);
describe('rendering', () => { describe('rendering', () => {
test('it renders the column headers', () => { test('it renders the column headers', () => {

View file

@ -15,10 +15,11 @@ import {
EuiContextMenuPanelItemDescriptor, EuiContextMenuPanelItemDescriptor,
} from '@elastic/eui'; } from '@elastic/eui';
import uuid from 'uuid'; import uuid from 'uuid';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch } from 'react-redux';
import { BrowserFields } from '../../../../common/containers/source'; import { BrowserFields } from '../../../../common/containers/source';
import { TimelineType } from '../../../../../common/types/timeline'; import { TimelineType } from '../../../../../common/types/timeline';
import { useShallowEqualSelector } from '../../../../common/hooks/use_selector';
import { StatefulEditDataProvider } from '../../edit_data_provider'; import { StatefulEditDataProvider } from '../../edit_data_provider';
import { addContentToTimeline } from './helpers'; import { addContentToTimeline } from './helpers';
import { DataProviderType } from './data_provider'; import { DataProviderType } from './data_provider';
@ -36,7 +37,7 @@ const AddDataProviderPopoverComponent: React.FC<AddDataProviderPopoverProps> = (
}) => { }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const [isAddFilterPopoverOpen, setIsAddFilterPopoverOpen] = useState(false); const [isAddFilterPopoverOpen, setIsAddFilterPopoverOpen] = useState(false);
const timelineById = useSelector(timelineSelectors.timelineByIdSelector); const timelineById = useShallowEqualSelector(timelineSelectors.timelineByIdSelector);
const { dataProviders, timelineType } = timelineById[timelineId] ?? {}; const { dataProviders, timelineType } = timelineById[timelineId] ?? {};
const handleOpenPopover = useCallback(() => setIsAddFilterPopoverOpen(true), [ const handleOpenPopover = useCallback(() => setIsAddFilterPopoverOpen(true), [

View file

@ -6,10 +6,11 @@
import { noop } from 'lodash/fp'; import { noop } from 'lodash/fp';
import React, { useCallback, useEffect, useMemo, useState } from 'react'; import React, { useCallback, useEffect, useMemo, useState } from 'react';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch } from 'react-redux';
import { TimelineType } from '../../../../../common/types/timeline'; import { TimelineType } from '../../../../../common/types/timeline';
import { BrowserFields } from '../../../../common/containers/source'; import { BrowserFields } from '../../../../common/containers/source';
import { useShallowEqualSelector } from '../../../../common/hooks/use_selector';
import { timelineSelectors } from '../../../store/timeline'; import { timelineSelectors } from '../../../store/timeline';
import { OnDataProviderEdited } from '../events'; import { OnDataProviderEdited } from '../events';
@ -59,7 +60,7 @@ export const ProviderItemBadge = React.memo<ProviderItemBadgeProps>(
val, val,
type = DataProviderType.default, type = DataProviderType.default,
}) => { }) => {
const timelineById = useSelector(timelineSelectors.timelineByIdSelector); const timelineById = useShallowEqualSelector(timelineSelectors.timelineByIdSelector);
const timelineType = timelineId ? timelineById[timelineId]?.timelineType : TimelineType.default; const timelineType = timelineId ? timelineById[timelineId]?.timelineType : TimelineType.default;
const { getManageTimelineById } = useManageTimeline(); const { getManageTimelineById } = useManageTimeline();
const isLoading = useMemo(() => getManageTimelineById(timelineId ?? '').isLoading, [ const isLoading = useMemo(() => getManageTimelineById(timelineId ?? '').isLoading, [

View file

@ -5,7 +5,9 @@
*/ */
import { useCallback, useState, useEffect } from 'react'; import { useCallback, useState, useEffect } from 'react';
import { useDispatch, useSelector, shallowEqual } from 'react-redux'; import { useDispatch } from 'react-redux';
import { useShallowEqualSelector } from '../../../../common/hooks/use_selector';
import { SecurityPageName } from '../../../../../common/constants'; import { SecurityPageName } from '../../../../../common/constants';
import { getTimelineUrl, useFormatUrl } from '../../../../common/components/link_to'; import { getTimelineUrl, useFormatUrl } from '../../../../common/components/link_to';
import { CursorPosition } from '../../../../common/components/markdown_editor'; import { CursorPosition } from '../../../../common/components/markdown_editor';
@ -20,7 +22,7 @@ export const useInsertTimeline = (value: string, onChange: (newValue: string) =>
end: 0, end: 0,
}); });
const insertTimeline = useSelector(timelineSelectors.selectInsertTimeline, shallowEqual); const insertTimeline = useShallowEqualSelector(timelineSelectors.selectInsertTimeline);
const handleOnTimelineChange = useCallback( const handleOnTimelineChange = useCallback(
(title: string, id: string | null, graphEventId?: string) => { (title: string, id: string | null, graphEventId?: string) => {

View file

@ -20,7 +20,7 @@ import {
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import uuid from 'uuid'; import uuid from 'uuid';
import styled from 'styled-components'; import styled from 'styled-components';
import { useDispatch, useSelector } from 'react-redux'; import { useDispatch } from 'react-redux';
import { APP_ID } from '../../../../../common/constants'; import { APP_ID } from '../../../../../common/constants';
import { import {
@ -33,9 +33,9 @@ import {
import { SecurityPageName } from '../../../../app/types'; import { SecurityPageName } from '../../../../app/types';
import { timelineSelectors } from '../../../../timelines/store/timeline'; import { timelineSelectors } from '../../../../timelines/store/timeline';
import { getCreateCaseUrl } from '../../../../common/components/link_to'; import { getCreateCaseUrl } from '../../../../common/components/link_to';
import { State } from '../../../../common/store';
import { useKibana } from '../../../../common/lib/kibana'; import { useKibana } from '../../../../common/lib/kibana';
import { Note } from '../../../../common/lib/note'; import { Note } from '../../../../common/lib/note';
import { useShallowEqualSelector } from '../../../../common/hooks/use_selector';
import { Notes } from '../../notes'; import { Notes } from '../../notes';
import { AssociateNote, UpdateNote } from '../../notes/helpers'; import { AssociateNote, UpdateNote } from '../../notes/helpers';
@ -159,7 +159,7 @@ interface NewCaseProps {
export const NewCase = React.memo<NewCaseProps>( export const NewCase = React.memo<NewCaseProps>(
({ compact, graphEventId, onClosePopover, timelineId, timelineStatus, timelineTitle }) => { ({ compact, graphEventId, onClosePopover, timelineId, timelineStatus, timelineTitle }) => {
const dispatch = useDispatch(); const dispatch = useDispatch();
const { savedObjectId } = useSelector((state: State) => const { savedObjectId } = useShallowEqualSelector((state) =>
timelineSelectors.selectTimeline(state, timelineId) timelineSelectors.selectTimeline(state, timelineId)
); );
const { navigateToApp } = useKibana().services.application; const { navigateToApp } = useKibana().services.application;

View file

@ -4,8 +4,9 @@
* you may not use this file except in compliance with the Elastic License. * you may not use this file except in compliance with the Elastic License.
*/ */
import React, { useCallback, useMemo } from 'react'; import React, { useCallback, useMemo } from 'react';
import { shallowEqual, useDispatch, useSelector } from 'react-redux'; import { useDispatch } from 'react-redux';
import { EuiButton, EuiButtonEmpty } from '@elastic/eui'; import { EuiButton, EuiButtonEmpty } from '@elastic/eui';
import { defaultHeaders } from '../body/column_headers/default_headers'; import { defaultHeaders } from '../body/column_headers/default_headers';
import { timelineActions } from '../../../store/timeline'; import { timelineActions } from '../../../store/timeline';
import { useFullScreen } from '../../../../common/containers/use_full_screen'; import { useFullScreen } from '../../../../common/containers/use_full_screen';
@ -14,9 +15,9 @@ import {
TimelineType, TimelineType,
TimelineTypeLiteral, TimelineTypeLiteral,
} from '../../../../../common/types/timeline'; } from '../../../../../common/types/timeline';
import { useShallowEqualSelector } from '../../../../common/hooks/use_selector';
import { inputsActions, inputsSelectors } from '../../../../common/store/inputs'; import { inputsActions, inputsSelectors } from '../../../../common/store/inputs';
import { sourcererActions, sourcererSelectors } from '../../../../common/store/sourcerer'; import { sourcererActions, sourcererSelectors } from '../../../../common/store/sourcerer';
import { State } from '../../../../common/store';
import { SourcererScopeName } from '../../../../common/store/sourcerer/model'; import { SourcererScopeName } from '../../../../common/store/sourcerer/model';
export const useCreateTimelineButton = ({ export const useCreateTimelineButton = ({
@ -33,9 +34,9 @@ export const useCreateTimelineButton = ({
() => sourcererSelectors.getAllExistingIndexNamesSelector(), () => sourcererSelectors.getAllExistingIndexNamesSelector(),
[] []
); );
const existingIndexNames = useSelector<State, string[]>(existingIndexNamesSelector, shallowEqual); const existingIndexNames = useShallowEqualSelector<string[]>(existingIndexNamesSelector);
const { timelineFullScreen, setTimelineFullScreen } = useFullScreen(); const { timelineFullScreen, setTimelineFullScreen } = useFullScreen();
const globalTimeRange = useSelector(inputsSelectors.globalTimeRangeSelector); const globalTimeRange = useShallowEqualSelector(inputsSelectors.globalTimeRangeSelector);
const createTimeline = useCallback( const createTimeline = useCallback(
({ id, show }) => { ({ id, show }) => {
if (id === TimelineId.active && timelineFullScreen) { if (id === TimelineId.active && timelineFullScreen) {