feat(rtk-query): add fallback message if there are no rtk-query apis

This commit is contained in:
FaberVitale 2021-06-21 13:22:25 +02:00
parent 3598bc8b3c
commit 9f1d718e80
7 changed files with 56 additions and 6 deletions

View File

@ -10,3 +10,4 @@ __snapshots__
dev dev
.yarn/* .yarn/*
**/.yarn/* **/.yarn/*
demo/public/**

View File

@ -124,7 +124,7 @@ class RtkQueryInspector<S, A extends Action<unknown>> extends Component<
this.selectors.selectAllVisbileQueries(selectorsSource); this.selectors.selectAllVisbileQueries(selectorsSource);
const currentQueryInfo = const currentQueryInfo =
this.selectors.selectorCurrentQueryInfo(selectorsSource); this.selectors.selectCurrentQueryInfo(selectorsSource);
const currentRtkApi = getApiStateOf(currentQueryInfo, apiStates); const currentRtkApi = getApiStateOf(currentQueryInfo, apiStates);
const currentQuerySubscriptions = getQuerySubscriptionsOf( const currentQuerySubscriptions = getQuerySubscriptionsOf(
@ -137,6 +137,8 @@ class RtkQueryInspector<S, A extends Action<unknown>> extends Component<
const currentApiStats = const currentApiStats =
this.selectors.selectApiStatsOfCurrentQuery(selectorsSource); this.selectors.selectApiStatsOfCurrentQuery(selectorsSource);
const hasNoApis = apiStates == null;
return ( return (
<div <div
ref={this.inspectorRef} ref={this.inspectorRef}
@ -167,6 +169,7 @@ class RtkQueryInspector<S, A extends Action<unknown>> extends Component<
apiState={currentRtkApi} apiState={currentRtkApi}
isWideLayout={isWideLayout} isWideLayout={isWideLayout}
apiStats={currentApiStats} apiStats={currentApiStats}
hasNoApis={hasNoApis}
/> />
</div> </div>
); );

View File

@ -0,0 +1,23 @@
import React from 'react';
import { ReactNode } from 'react';
import { StyleUtilsContext } from '../styles/createStylingFromTheme';
export function NoRtkQueryApi(): ReactNode {
return (
<StyleUtilsContext.Consumer>
{({ styling }) => (
<div {...styling('noApiFound')}>
No rtk-query api found.<br/>Make sure to follow{' '}
<a
href="https://redux-toolkit.js.org/rtk-query/overview#basic-usage"
target="_blank"
rel="noreferrer"
>
the instructions
</a>
.
</div>
)}
</StyleUtilsContext.Consumer>
);
}

View File

@ -11,10 +11,12 @@ import { QueryPreviewInfo } from './QueryPreviewInfo';
import { QueryPreviewApi } from './QueryPreviewApi'; import { QueryPreviewApi } from './QueryPreviewApi';
import { QueryPreviewSubscriptions } from './QueryPreviewSubscriptions'; import { QueryPreviewSubscriptions } from './QueryPreviewSubscriptions';
import { QueryPreviewTags } from './QueryPreviewTags'; import { QueryPreviewTags } from './QueryPreviewTags';
import { NoRtkQueryApi } from './NoRtkQueryApi';
export interface QueryPreviewProps export interface QueryPreviewProps
extends Omit<QueryPreviewTabProps, 'base16Theme' | 'invertTheme'> { extends Omit<QueryPreviewTabProps, 'base16Theme' | 'invertTheme'> {
selectedTab: QueryPreviewTabs; selectedTab: QueryPreviewTabs;
hasNoApis: boolean;
onTabChange: (tab: QueryPreviewTabs) => void; onTabChange: (tab: QueryPreviewTabs) => void;
} }
@ -95,6 +97,7 @@ export class QueryPreview extends React.PureComponent<QueryPreviewProps> {
querySubscriptions, querySubscriptions,
tags, tags,
apiStats, apiStats,
hasNoApis,
} = this.props; } = this.props;
const { component: TabComponent } = const { component: TabComponent } =
@ -111,6 +114,7 @@ export class QueryPreview extends React.PureComponent<QueryPreviewProps> {
tabs={tabs} tabs={tabs}
renderTabLabel={this.renderTabLabel} renderTabLabel={this.renderTabLabel}
/> />
{hasNoApis && <NoRtkQueryApi />}
</div> </div>
)} )}
</StyleUtilsContext.Consumer> </StyleUtilsContext.Consumer>

View File

@ -48,7 +48,7 @@ export interface InspectorSelectors<S> {
ReturnType<typeof extractAllApiQueries> ReturnType<typeof extractAllApiQueries>
>; >;
readonly selectAllVisbileQueries: InspectorSelector<S, QueryInfo[]>; readonly selectAllVisbileQueries: InspectorSelector<S, QueryInfo[]>;
readonly selectorCurrentQueryInfo: InspectorSelector<S, QueryInfo | null>; readonly selectCurrentQueryInfo: InspectorSelector<S, QueryInfo | null>;
readonly selectSearchQueryRegex: InspectorSelector<S, RegExp | null>; readonly selectSearchQueryRegex: InspectorSelector<S, RegExp | null>;
readonly selectCurrentQueryTags: InspectorSelector<S, RtkQueryTag[]>; readonly selectCurrentQueryTags: InspectorSelector<S, RtkQueryTag[]>;
readonly selectApiStatsOfCurrentQuery: InspectorSelector<S, ApiStats | null>; readonly selectApiStatsOfCurrentQuery: InspectorSelector<S, ApiStats | null>;
@ -112,7 +112,7 @@ export function createInspectorSelectors<S>(): InspectorSelectors<S> {
} }
); );
const selectorCurrentQueryInfo = createSelector( const selectCurrentQueryInfo = createSelector(
selectAllQueries, selectAllQueries,
({ monitorState }: SelectorsSource<S>) => monitorState.selectedQueryKey, ({ monitorState }: SelectorsSource<S>) => monitorState.selectedQueryKey,
(allQueries, selectedQueryKey) => { (allQueries, selectedQueryKey) => {
@ -133,13 +133,13 @@ export function createInspectorSelectors<S>(): InspectorSelectors<S> {
const selectCurrentQueryTags = createSelector( const selectCurrentQueryTags = createSelector(
selectApiStates, selectApiStates,
selectorCurrentQueryInfo, selectCurrentQueryInfo,
(apiState, currentQueryInfo) => getQueryTagsOf(currentQueryInfo, apiState) (apiState, currentQueryInfo) => getQueryTagsOf(currentQueryInfo, apiState)
); );
const selectApiStatsOfCurrentQuery = createSelector( const selectApiStatsOfCurrentQuery = createSelector(
selectApiStates, selectApiStates,
selectorCurrentQueryInfo, selectCurrentQueryInfo,
(apiState, currentQueryInfo) => (apiState, currentQueryInfo) =>
generateApiStatsOfCurrentQuery(currentQueryInfo, apiState) generateApiStatsOfCurrentQuery(currentQueryInfo, apiState)
); );
@ -150,7 +150,7 @@ export function createInspectorSelectors<S>(): InspectorSelectors<S> {
selectAllQueries, selectAllQueries,
selectAllVisbileQueries, selectAllVisbileQueries,
selectSearchQueryRegex, selectSearchQueryRegex,
selectorCurrentQueryInfo, selectCurrentQueryInfo,
selectCurrentQueryTags, selectCurrentQueryTags,
selectApiStatsOfCurrentQuery, selectApiStatsOfCurrentQuery,
}; };

View File

@ -289,6 +289,16 @@ const getSheetFromColorMap = (map: ColorMap) => {
}, },
}, },
noApiFound: {
width: '100%',
textAlign: 'center',
padding: '1.4em',
'& a': {
fontSize: 'inherit',
textDecoration: 'underline',
},
},
searchSelectLabel: { searchSelectLabel: {
display: 'inline-block', display: 'inline-block',
padding: 4, padding: 4,

View File

@ -41,6 +41,15 @@ export function isApiSlice(val: unknown): val is RtkQueryApiState {
return true; return true;
} }
/**
* Indexes api states by their `reducerPath`.
*
* Returns `null` if there are no api slice or `reduxStoreState`
* is not an object.
*
* @param reduxStoreState
* @returns
*/
export function getApiStatesOf( export function getApiStatesOf(
reduxStoreState: unknown reduxStoreState: unknown
): null | Readonly<Record<string, RtkQueryApiState>> { ): null | Readonly<Record<string, RtkQueryApiState>> {