Skip to content

Commit 53b5f26

Browse files
committed
Update DataState to use LoadingPulse by default, instead of LoadingIndicator
1 parent ca37cf6 commit 53b5f26

File tree

7 files changed

+58
-48
lines changed

7 files changed

+58
-48
lines changed

src/components/common/indicators/loading-pulse-static.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@ import LoadingPulse from './loading-pulse';
55
export default function LoadingPulseStatic<T>(props: {
66
content: string,
77
dataState: DataState<T>,
8-
className: string, // Requires className only to set background color, width is derived from content!
8+
className?: string, // Set background with text-color, takes background from currentcolor!
99
}) {
1010
return props.dataState.error || props.dataState.value ?
1111
props.content

src/components/common/indicators/loading-pulse.tsx

Lines changed: 5 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -1,8 +1,9 @@
1-
export default function LoadingPulse(props: { className: string, content?: string }) {
2-
return ( // Requires className to set background color as well as width (unless content is used)!
3-
<span className={`${props.className} animate-pulse-strong inline-block align-middle rounded-full h-[1em]`}>
1+
export default function LoadingPulse(props: { className?: string, content?: string }) {
2+
return ( // Set background with text-color, takes background from currentcolor!
3+
<span className={`${props.className} inline-block h-[1em]
4+
bg-[currentcolor] animate-pulse-strong align-middle rounded-full`}>
45
<span className='invisible'>
5-
{props.content ?? ' '}
6+
{props.content ?? '\xa0'}
67
</span>
78
</span>
89
);

src/components/content/home-page/blocks/block-reward.tsx

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,5 @@
11
import { useDataState, FetchError } from '@/lib/data-state';
22
import { getBlockRewardUrl, getEtherValueFromWei } from '@/lib/utilities';
3-
import LoadingPulse from '@/components/common/indicators/loading-pulse';
43
import LoadingPulseStatic from '@/components/common/indicators/loading-pulse-static';
54
import ErrorWithRefetch from '@/components/common/indicators/error-with-refetch';
65
import ValueWithRefetch from '@/components/common/indicators/value-with-refetch';
@@ -34,13 +33,13 @@ export default function BlockReward(props: {
3433
<LoadingPulseStatic
3534
content='Block Reward:'
3635
dataState={blockRewardData}
37-
className='bg-(--grey-fg-color)'
36+
className='text-(--grey-fg-color)'
3837
/>
3938
&nbsp;&nbsp;
4039
<blockRewardData.Render
4140
value={ () => blockReward }
42-
loadingFallback={<LoadingPulse className='bg-(--grey-fg-color) w-[4rem]' />}
4341
errorFallback={errorFallback}
42+
className='w-[4rem] text-(--grey-fg-color)'
4443
/>
4544
</span>
4645
);

src/components/content/home-page/blocks/block.tsx

Lines changed: 10 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,6 @@ import {
1111
import { useDataState, DataState } from '@/lib/data-state';
1212
import Link from 'next/link';
1313
import PopoverLink from '../../../common/popover-link';
14-
import LoadingPulse from '@/components/common/indicators/loading-pulse';
1514
import LoadingPulseStatic from '@/components/common/indicators/loading-pulse-static';
1615
import ErrorWithRefetch from '@/components/common/indicators/error-with-refetch';
1716
import BlockReward from './block-reward';
@@ -35,21 +34,21 @@ export default function Block(props: {
3534
<div className='flex flex-col md:flex-row'>
3635
<div className='flex'>
3736
<CubeIcon className='w-10 h-10 md:w-8 md:h-8' />
38-
<div className='flex md:flex-col ml-2 pt-1 md:pt-0 md:w-32'>
39-
<span className='px-2 md:px-4 leading-5'>
37+
<div className='flex md:flex-col ml-2 pt-1 md:pt-0 md:w-[8rem] px-2 md:px-4'>
38+
<span className='leading-5'>
4039
<props.latestBlockData.Render
41-
value={() => <Link href={`/${props.network}/block?number=${blockNumber}`}
42-
className='text-(--link-color) hover:text-(--hover-fg-color)'>
40+
value={(className) => <Link href={`/${props.network}/block?number=${blockNumber}`}
41+
className={`${className} hover:text-(--hover-fg-color)`}>
4342
{blockNumber}
4443
</Link>}
45-
loadingFallback={<LoadingPulse className='bg-(--link-color) w-[5rem]' />}
44+
className='text-(--link-color) w-[5em]'
4645
/>
4746
</span>
48-
<span className='md:pl-4 text-sm text-(--grey-fg-color)'>
47+
<span className='text-sm text-(--grey-fg-color)'>
4948
<blockData.Render
5049
value={() => `(${getBlockAgeFromSecs(getSecsFromUnixSecs(blockData.value!.timestamp))} ago)`}
51-
loadingFallback={<LoadingPulse className='bg-(--grey-fg-color) w-[6rem]' />}
5250
errorFallback={<ErrorWithRefetch refetch={blockData.fetch} />}
51+
className='w-[6em]'
5352
/>
5453
</span>
5554
</div>
@@ -64,15 +63,15 @@ export default function Block(props: {
6463
<span className='px-2 md:px-4 leading-5'>
6564
<blockData.Render
6665
value={() => `${blockData.value!.transactions.length} transactions`}
67-
loadingFallback={<LoadingPulse className='bg-(--grey-fg-color) w-[8rem]' />}
6866
errorFallback={<ErrorWithRefetch refetch={blockData.fetch} />}
67+
className='text-(--grey-fg-color) w-[8rem]'
6968
/>
7069
</span>
7170
<span className='pl-2 md:pl-4 leading-5'>
7271
<LoadingPulseStatic
7372
content='Recipient:'
7473
dataState={blockData}
75-
className='bg-(--grey-fg-color)'
74+
className='text-(--grey-fg-color)'
7675
/>
7776
&nbsp;&nbsp;
7877
<blockData.Render
@@ -83,8 +82,8 @@ export default function Block(props: {
8382
popover={blockData.value!.miner}
8483
className='left-[-37%] top-[-2.6rem] w-78 py-1.5 px-2.5'
8584
/>}
86-
loadingFallback={<LoadingPulse className='bg-(--link-color) w-[11rem]' />}
8785
errorFallback={<ErrorWithRefetch refetch={blockData.fetch} />}
86+
className='text-(--link-color) w-[11rem]'
8887
/>
8988
</span>
9089
</div>

src/components/content/home-page/stats/stat-card.tsx

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import { ReactNode } from 'react';
22
import { DataState } from '@/lib/data-state';
33
import ErrorWithRefetch from '@/components/common/indicators/error-with-refetch';
4+
import LoadingIndicator from '@/components/common/indicators/loading-indicator';
45

56

67
export default function StatCard<T>(props: {
@@ -24,6 +25,7 @@ export default function StatCard<T>(props: {
2425
<props.dataState.Render
2526
value={props.value}
2627
errorFallback={<ErrorWithRefetch refetch={props.dataState.fetch} />}
28+
loadingFallback={<LoadingIndicator />}
2729
/>
2830
</div>
2931
</div>

src/components/content/home-page/transactions/transaction.tsx

Lines changed: 25 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import { BlockWithTransactions } from 'alchemy-sdk';
55
import { truncateAddress, truncateTransaction, getEtherValueFromWei } from '@/lib/utilities';
66
import PopoverLink from '@/components/common/popover-link';
77
import { DataState } from '@/lib/data-state';
8-
import LoadingPulse from '@/components/common/indicators/loading-pulse';
98
import LoadingPulseStatic from '@/components/common/indicators/loading-pulse-static';
109

1110

@@ -15,7 +14,12 @@ export default function Transaction(props: {
1514
blockWithTransactions: DataState<BlockWithTransactions>,
1615
}) {
1716
// Use a callback because the transactions might still be loading:
18-
const transaction = () => props.blockWithTransactions.value!.transactions[props.id];
17+
const transaction = props.blockWithTransactions.value?.transactions[props.id];
18+
19+
const hash = transaction?.hash;
20+
const ethValue = transaction?.value;
21+
const from = transaction?.from;
22+
const to = transaction?.to;
1923

2024
return (
2125
<div className='md:min-h-[4.825rem] p-2 md:p-3 border-b border-(--border-color) last:border-0'>
@@ -26,25 +30,25 @@ export default function Transaction(props: {
2630
<span className='px-2 md:px-4'>
2731
<props.blockWithTransactions.Render
2832
value={() =>
29-
<PopoverLink
30-
href={`/${props.network}/transaction?hash=${transaction().hash}`}
31-
content={truncateTransaction(transaction().hash, 18)}
32-
popover={transaction().hash}
33+
<PopoverLink // runtime error: transaction() undefined!?
34+
href={`/${props.network}/transaction?hash=${hash}`}
35+
content={truncateTransaction(hash!, 18)}
36+
popover={hash!}
3337
className='-left-full top-[-2.6rem] w-120 py-1.5 px-2.5'
3438
/>}
35-
loadingFallback={<LoadingPulse className='bg-(--link-color) w-[10rem]' />}
39+
className='text-(--link-color) w-[10rem]'
3640
/>
3741
</span>
3842
<span className='px-2 md:pl-4'>
3943
<LoadingPulseStatic
4044
content='Amount:'
4145
dataState={props.blockWithTransactions}
42-
className='bg-(--grey-fg-color)'
46+
className='text-(--grey-fg-color)'
4347
/>
4448
&nbsp;&nbsp;
4549
<props.blockWithTransactions.Render
46-
value={() => ${getEtherValueFromWei(transaction().value, 6)}`}
47-
loadingFallback={<LoadingPulse className='bg-(--grey-fg-color) w-[3rem]' />}
50+
value={() => ${getEtherValueFromWei(ethValue!, 6)}`}
51+
className='text-(--grey-fg-color) w-[3rem]'
4852
/>
4953
</span>
5054
</div>
@@ -55,37 +59,37 @@ export default function Transaction(props: {
5559
<LoadingPulseStatic
5660
content='From:'
5761
dataState={props.blockWithTransactions}
58-
className='bg-(--grey-fg-color)'
62+
className='text-(--grey-fg-color)'
5963
/>
6064
&nbsp;&nbsp;
6165
<props.blockWithTransactions.Render
6266
value={() =>
6367
<PopoverLink
64-
href={`/${props.network}/address?hash=${transaction().from}`}
65-
content={truncateAddress(transaction().from, 21)}
66-
popover={transaction().from}
68+
href={`/${props.network}/address?hash=${transaction?.from}`}
69+
content={truncateAddress(transaction?.from!, 21)}
70+
popover={transaction?.from!}
6771
className='left-[-35%] top-[-2.6rem] w-78 py-1.5 px-2.5'
6872
/>}
69-
loadingFallback={<LoadingPulse className='bg-(--link-color) w-[11.5rem]' />}
73+
className='text-(--link-color) w-[11.25rem]'
7074
/>
7175
</span>
7276
<span className='pl-7 md:pl-9'>
7377
<LoadingPulseStatic
7478
content='To:'
7579
dataState={props.blockWithTransactions}
76-
className='bg-(--grey-fg-color)'
80+
className='text-(--grey-fg-color)'
7781
/>
7882
&nbsp;&nbsp;
7983
<props.blockWithTransactions.Render
80-
value={() => transaction().to ?
84+
value={() => transaction?.to ?
8185
<PopoverLink
82-
href={`/${props.network}/address?hash=${transaction().to}`}
83-
content={truncateAddress(transaction().to!, 21)}
84-
popover={transaction().to!}
86+
href={`/${props.network}/address?hash=${transaction?.to}`}
87+
content={truncateAddress(transaction?.to!, 21)}
88+
popover={transaction?.to!}
8589
className='left-[-35%] top-[-2.6rem] w-78 py-1.5 px-2.5'
8690
/>
8791
: <span>/</span>}
88-
loadingFallback={<LoadingPulse className='bg-(--link-color) w-[11.5rem]' />}
92+
className='text-(--link-color) w-[11.25rem]'
8993
/>
9094
</span>
9195
</div>

src/lib/data-state.tsx

Lines changed: 13 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import { Dispatch, ReactNode, SetStateAction, useCallback, useEffect, useMemo, useRef, useState } from 'react';
2-
import LoadingIndicator from '@/components/common/indicators/loading-indicator';
32
import ErrorIndicator from '@/components/common/indicators/error-indicator';
3+
import LoadingPulse from '@/components/common/indicators/loading-pulse';
44

55

66
type ValueRoot<T> = {
@@ -54,7 +54,7 @@ interface DataStateMethods<T> {
5454
// either the `ValueState`'s value, or the `ErrorState`'s error.
5555
interface RenderConfig {
5656
// Optional callback function for rendering a subfield of the `ValueState`'s value IFF that value is present:
57-
value?: () => ReactNode;
57+
value?: (className?: string) => ReactNode;
5858
// Optional short error to display instead of full error:
5959
error?: string;
6060
// Optionally don't display fallback components like Loading- or ErrorIndicators:
@@ -63,8 +63,8 @@ interface RenderConfig {
6363
loadingFallback?: ReactNode;
6464
// Optionally display another component instead of the default ErrorIndicator:
6565
errorFallback?: ReactNode;
66-
// Optional className for the fallback component when it exists:
67-
fallbackClass?: string;
66+
// Optional className for the displayed component:
67+
className?: string;
6868
}
6969

7070
// FetchConfig is used to initialize a DataState<T>, which is a DataRoot<T>,
@@ -162,18 +162,23 @@ export const DataState = {
162162
const useInit = () => useEffect(() => { fetch() }, [fetch]);
163163

164164
const Render = (conf: RenderConfig = {}): ReactNode => {
165-
const { value, error, showFallback = true, loadingFallback, errorFallback, fallbackClass } = conf;
165+
const { value, error, showFallback = true, loadingFallback, errorFallback, className } = conf;
166166

167-
if (dataRoot.value) return value ? value() : String(dataRoot.value);
167+
if (dataRoot.value) {
168+
return value ?
169+
value(className)
170+
:
171+
<span className={className}>{String(dataRoot.value)}</span>;
172+
}
168173
else if (dataRoot.error) {
169174
if (showFallback) {
170175
return errorFallback ?
171-
errorFallback : <ErrorIndicator error={error} className={fallbackClass} />;
176+
errorFallback : <ErrorIndicator error={error} className={className} />;
172177
}
173178
}
174179
else if (showFallback) {
175180
return loadingFallback ?
176-
loadingFallback : <LoadingIndicator className={fallbackClass} />;
181+
loadingFallback : <LoadingPulse className={className} />;
177182
}
178183
}
179184

0 commit comments

Comments
 (0)