useCallback for onChange in react-params (#2705)

* useCallback for onChange in react-params

* Use keyed events
This commit is contained in:
Jaco Greeff 2020-05-08 11:50:36 +02:00 committed by GitHub
parent 82f934f73c
commit 0ed8bd1611
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 179 additions and 188 deletions

View File

@ -3,6 +3,7 @@
// of the Apache-2.0 license. See the LICENSE file for details.
import { EventRecord, SignedBlock } from '@polkadot/types/interfaces';
import { KeyedEvent } from '../types';
import React from 'react';
import { Link } from 'react-router-dom';
@ -24,7 +25,14 @@ interface Props {
function BlockByHash ({ className, value }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const { api } = useApi();
const events = useCall<EventRecord[]>(api.query.system.events.at, [value], { isSingle: true });
const events = useCall<KeyedEvent[]>(api.query.system.events.at, [value], {
isSingle: true,
transform: (events: EventRecord[]): KeyedEvent[] =>
events.map((record) => ({
key: `${Date.now()}-${record.hash.toHex()}`,
record
}))
});
const getBlock = useCall<SignedBlock>(api.rpc.chain.getBlock, [value], { isSingle: true });
const getHeader = useCall<HeaderExtended>(api.derive.chain.getHeader, [value]);
@ -79,7 +87,7 @@ function BlockByHash ({ className, value }: Props): React.ReactElement<Props> {
<Column>
<Events
eventClassName='explorer--BlockByHash-block'
events={(events || []).filter(({ phase }) => !phase.isApplyExtrinsic)}
events={events}
label={t('system events')}
/>
</Column>

View File

@ -2,7 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { BlockNumber, EventRecord, Extrinsic } from '@polkadot/types/interfaces';
import { BlockNumber, Extrinsic } from '@polkadot/types/interfaces';
import { KeyedEvent } from '../types';
import React from 'react';
import styled from 'styled-components';
@ -16,7 +17,7 @@ import Event from '../Event';
interface Props {
blockNumber?: BlockNumber;
className?: string;
events?: EventRecord[];
events?: KeyedEvent[];
index: number;
value: Extrinsic;
}
@ -31,8 +32,8 @@ function getEra ({ era }: Extrinsic, blockNumber?: BlockNumber): [number, number
return null;
}
function filterEvents (index: number, events: EventRecord[] = []): EventRecord[] {
return events.filter(({ phase }) => phase.isApplyExtrinsic && phase.asApplyExtrinsic.eq(index));
function filterEvents (index: number, events: KeyedEvent[] = []): KeyedEvent[] {
return events.filter(({ record: { phase } }) => phase.isApplyExtrinsic && phase.asApplyExtrinsic.eq(index));
}
function ExtrinsicDisplay ({ blockNumber, className, events, index, value }: Props): React.ReactElement<Props> {
@ -76,11 +77,11 @@ function ExtrinsicDisplay ({ blockNumber, className, events, index, value }: Pro
className='top'
colSpan={2}
>
{thisEvents.map((event, index) =>
{thisEvents.map(({ key, record }) =>
<Event
className='explorer--BlockByHash-event'
key={`event:${index}`}
value={event}
key={key}
value={record}
/>
)}
</td>

View File

@ -2,7 +2,8 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { BlockNumber, EventRecord, Extrinsic } from '@polkadot/types/interfaces';
import { BlockNumber, Extrinsic } from '@polkadot/types/interfaces';
import { KeyedEvent } from '../types';
import React, { useMemo } from 'react';
import { Table } from '@polkadot/react-components';
@ -13,7 +14,7 @@ import ExtrinsicDisplay from './Extrinsic';
interface Props {
blockNumber?: BlockNumber;
className?: string;
events?: EventRecord[];
events?: KeyedEvent[];
label?: React.ReactNode;
value?: Extrinsic[] | null;
}

View File

@ -2,7 +2,7 @@
// This software may be modified and distributed under the terms
// of the Apache-2.0 license. See the LICENSE file for details.
import { EventRecord } from '@polkadot/types/interfaces';
import { KeyedEvent } from './types';
import React, { useMemo } from 'react';
import { Table } from '@polkadot/react-components';
@ -12,7 +12,7 @@ import { useTranslation } from './translate';
interface Props {
emptyLabel?: React.ReactNode;
events: EventRecord[];
events?: KeyedEvent[];
eventClassName?: string;
label?: React.ReactNode;
}
@ -29,15 +29,15 @@ function Events ({ emptyLabel, eventClassName, events, label }: Props): React.Re
empty={emptyLabel || t('No events available')}
header={header}
>
{events
.filter(({ event: { method, section } }): boolean => !!method && !!section)
.map((event: EventRecord, index): React.ReactNode => (
{events && events
.filter(({ record: { event: { method, section } } }) => !!method && !!section)
.map(({ key, record }): React.ReactNode => (
<tr
className={eventClassName}
key={`event:${index}`}
key={key}
>
<td className='overflow'>
<Event value={event} />
<Event value={record} />
</td>
</tr>
))

View File

@ -28,7 +28,7 @@ function Main ({ events, headers }: Props): React.ReactElement<Props> {
<BlockHeaders headers={headers} />
</Column>
<Column>
<Events events={events.map(({ record }) => record)} />
<Events events={events} />
</Column>
</Columar>
</>

View File

@ -4,36 +4,36 @@
import { Props } from '../types';
import React from 'react';
import React, { useCallback, useState } from 'react';
import { InputAddress } from '@polkadot/react-components';
import keyring from '@polkadot/ui-keyring';
import Bare from './Bare';
function onChange ({ onChange }: Props): (_?: string | null) => void {
return (value?: string | null): void => {
let isValid = false;
function Account ({ className, defaultValue: { value }, isDisabled, isError, label, onChange, style, withLabel }: Props): React.ReactElement<Props> {
const [defaultValue] = useState(value?.toString());
if (value) {
try {
keyring.decodeAddress(value);
const _onChange = useCallback(
(value?: string | null): void => {
let isValid = false;
isValid = true;
} catch (err) {
console.error(err);
if (value) {
try {
keyring.decodeAddress(value);
isValid = true;
} catch (err) {
console.error(err);
}
}
}
onChange && onChange({
isValid,
value
});
};
}
function Account (props: Props): React.ReactElement<Props> {
const { className, defaultValue: { value }, isDisabled, isError, label, style, withLabel } = props;
const defaultValue = value && value.toString();
onChange && onChange({
isValid,
value
});
},
[onChange]
);
return (
<Bare
@ -47,7 +47,7 @@ function Account (props: Props): React.ReactElement<Props> {
isError={isError}
isInput
label={label}
onChange={onChange(props)}
onChange={_onChange}
placeholder='5...'
type='allPlus'
withEllipsis

View File

@ -5,7 +5,7 @@
import { Props } from '../types';
import BN from 'bn.js';
import React from 'react';
import React, { useCallback, useState } from 'react';
import { registry } from '@polkadot/react-api';
import { Input } from '@polkadot/react-components';
import { ClassOf } from '@polkadot/types';
@ -13,24 +13,25 @@ import { bnToBn, formatNumber } from '@polkadot/util';
import Bare from './Bare';
function onChange ({ onChange }: Props): (_: string) => void {
return function (value: string): void {
onChange && onChange({
isValid: true,
value: new BN(value || 0)
});
};
}
function Amount ({ className, defaultValue: { value }, isDisabled, isError, label, onChange, onEnter, style, withLabel }: Props): React.ReactElement<Props> {
const [defaultValue] = useState(
isDisabled
? (
value instanceof ClassOf(registry, 'AccountIndex')
? value.toString()
: formatNumber(value)
)
: bnToBn((value as number) || 0).toString()
);
function Amount (props: Props): React.ReactElement<Props> {
const { className, defaultValue: { value }, isDisabled, isError, label, onEnter, style, withLabel } = props;
const defaultValue = isDisabled
? (
value instanceof ClassOf(registry, 'AccountIndex')
? value.toString()
: formatNumber(value)
)
: bnToBn((value as number) || 0).toString();
const _onChange = useCallback(
(value: string) =>
onChange && onChange({
isValid: true,
value: new BN(value || 0)
}),
[onChange]
);
return (
<Bare
@ -44,7 +45,7 @@ function Amount (props: Props): React.ReactElement<Props> {
isError={isError}
label={label}
min={0}
onChange={onChange(props)}
onChange={_onChange}
onEnter={onEnter}
type={
isDisabled

View File

@ -43,6 +43,13 @@ function convertInput (value: string): [boolean, Uint8Array] {
}
function BaseBytes ({ asHex, children, className, defaultValue: { value }, isDisabled, isError, label, length = -1, onChange, onEnter, onEscape, size = 'full', style, validate = defaultValidate, withLabel, withLength }: Props): React.ReactElement<Props> {
const [defaultValue] = useState(
value
? isHex(value)
? value
: u8aToHex(value as Uint8Array, isDisabled ? 256 : -1)
: undefined
);
const [isValid, setIsValid] = useState(false);
useEffect((): void => {
@ -83,14 +90,6 @@ function BaseBytes ({ asHex, children, className, defaultValue: { value }, isDis
[asHex, length, onChange, validate, withLength]
);
const defaultValue = value
? (
isHex(value)
? value
: u8aToHex(value as Uint8Array, isDisabled ? 256 : -1)
)
: undefined;
return (
<Bare
className={className}

View File

@ -4,30 +4,36 @@
import { Props } from '../types';
import React from 'react';
import React, { useCallback, useMemo, useState } from 'react';
import { Dropdown } from '@polkadot/react-components';
import { useTranslation } from '../translate';
import Bare from './Bare';
const options = [
{ text: 'No', value: false },
{ text: 'Yes', value: true }
];
function BoolParam ({ className, defaultValue: { value }, isDisabled, isError, label, onChange, style, withLabel }: Props): React.ReactElement<Props> {
const { t } = useTranslation();
const [defaultValue] = useState(
value instanceof Boolean
? value.valueOf()
: value as boolean
);
function onChange ({ onChange }: Props): (_: boolean) => void {
return function (value: boolean): void {
onChange && onChange({
isValid: true,
value
});
};
}
const options = useMemo(
() => [
{ text: t('No'), value: false },
{ text: t('Yes'), value: true }
],
[t]
);
function BoolParam (props: Props): React.ReactElement<Props> {
const { className, defaultValue: { value }, isDisabled, isError, label, style, withLabel } = props;
const defaultValue = value instanceof Boolean
? value.valueOf()
: value as boolean;
const _onChange = useCallback(
(value: boolean) =>
onChange && onChange({
isValid: true,
value
}),
[onChange]
);
return (
<Bare
@ -40,7 +46,7 @@ function BoolParam (props: Props): React.ReactElement<Props> {
isDisabled={isDisabled}
isError={isError}
label={label}
onChange={onChange(props)}
onChange={_onChange}
options={options}
withEllipsis
withLabel={withLabel}

View File

@ -4,45 +4,35 @@
import { Props } from '../types';
import React from 'react';
import React, { useCallback } from 'react';
import Bytes from './Bytes';
import BytesFile from './File';
function renderDisabled ({ className, defaultValue, isError, label, onEnter, onEscape, style, type, withLabel }: Props): React.ReactNode {
return (
<Bytes
className={className}
defaultValue={defaultValue}
isError={isError}
label={label}
onEnter={onEnter}
onEscape={onEscape}
style={style}
type={type}
withLabel={withLabel}
/>
function Code ({ className, defaultValue, isDisabled, isError, label, onChange, onEnter, onEscape, style, type, withLabel }: Props): React.ReactElement<Props> {
// TODO: Validate that we have actual proper WASM code
const _onChange = useCallback(
(value: Uint8Array) =>
onChange && onChange({
isValid: value.length !== 0,
value
}),
[onChange]
);
}
// TODO: Validate that we have actual proper WASM code
function onChange ({ onChange }: Props): (_: Uint8Array) => void {
return function (value: Uint8Array): void {
onChange && onChange({
isValid: value.length !== 0,
value
});
};
}
function Code (props: Props): React.ReactElement<Props> {
const { className, defaultValue, isDisabled, isError, label, style, withLabel } = props;
if (isDisabled) {
return (
<>
{renderDisabled(props)}
</>
<Bytes
className={className}
defaultValue={defaultValue}
isError={isError}
label={label}
onEnter={onEnter}
onEscape={onEscape}
style={style}
type={type}
withLabel={withLabel}
/>
);
}
@ -52,7 +42,7 @@ function Code (props: Props): React.ReactElement<Props> {
defaultValue={defaultValue}
isError={isError}
label={label}
onChange={onChange(props)}
onChange={_onChange}
style={style}
withLabel={withLabel}
/>

View File

@ -4,43 +4,32 @@
import { Props, RawParamOnChangeValue } from '../types';
import React from 'react';
import React, { useCallback } from 'react';
import { Static } from '@polkadot/react-components';
import Amount from './Amount';
function renderDisabled ({ className, defaultValue, isError, label, style, withLabel }: Props): React.ReactNode {
return (
<Static
className={className}
defaultValue={
(defaultValue && defaultValue.value)
? defaultValue.value.toString()
: ''
}
isError={isError}
label={label}
style={style}
withLabel={withLabel}
/>
function Moment ({ className, defaultValue, isDisabled, isError, label, onChange, onEnter, onEscape, style, type, withLabel }: Props): React.ReactElement<Props> {
const _onChange = useCallback(
(value: RawParamOnChangeValue) =>
onChange && onChange(value),
[onChange]
);
}
// TODO: Validate that we have actual proper WASM code
function onChange ({ onChange }: Props): (_: RawParamOnChangeValue) => void {
return function (value: RawParamOnChangeValue): void {
onChange && onChange(value);
};
}
function Moment (props: Props): React.ReactElement<Props> {
const { className, defaultValue, isDisabled, isError, label, onEnter, onEscape, style, type, withLabel } = props;
if (isDisabled) {
return (
<>
{renderDisabled(props)}
</>
<Static
className={className}
defaultValue={
(defaultValue && defaultValue.value)
? defaultValue.value.toString()
: ''
}
isError={isError}
label={label}
style={style}
withLabel={withLabel}
/>
);
}
@ -51,7 +40,7 @@ function Moment (props: Props): React.ReactElement<Props> {
isDisabled={isDisabled}
isError={isError}
label={label}
onChange={onChange(props)}
onChange={_onChange}
onEnter={onEnter}
onEscape={onEscape}
style={style}

View File

@ -4,24 +4,24 @@
import { Props } from '../types';
import React from 'react';
import React, { useCallback } from 'react';
import { Input } from '@polkadot/react-components';
import Bare from './Bare';
function onChange ({ onChange }: Props): (_: string) => void {
return function (value: string): void {
const isValid = value.length !== 0;
function Raw ({ className, defaultValue: { value }, isDisabled, isError, label, onChange, onEnter, onEscape, style, withLabel }: Props): React.ReactElement<Props> {
const _onChange = useCallback(
(value: string): void => {
const isValid = value.length !== 0;
onChange && onChange({
isValid,
value
});
};
}
onChange && onChange({
isValid,
value
});
},
[onChange]
);
function Raw (props: Props): React.ReactElement<Props> {
const { className, defaultValue: { value }, isDisabled, isError, label, onEnter, onEscape, style, withLabel } = props;
const defaultValue = value
? (value.toHex ? value.toHex() : value)
: '';
@ -37,7 +37,7 @@ function Raw (props: Props): React.ReactElement<Props> {
isDisabled={isDisabled}
isError={isError}
label={label}
onChange={onChange(props)}
onChange={_onChange}
onEnter={onEnter}
onEscape={onEscape}
placeholder='Hex data'

View File

@ -4,24 +4,21 @@
import { Props } from '../types';
import React from 'react';
import React, { useCallback } from 'react';
import { Input } from '@polkadot/react-components';
import Bare from './Bare';
function onChange ({ onChange }: Props): (_: string) => void {
return function (value: string): void {
const isValid = value.length !== 0;
function Text ({ className, defaultValue: { value }, isDisabled, isError, label, onChange, onEnter, onEscape, style, withLabel }: Props): React.ReactElement<Props> {
const _onChange = useCallback(
(value: string) =>
onChange && onChange({
isValid: value.length !== 0,
value
}),
[onChange]
);
onChange && onChange({
isValid,
value
});
};
}
function Text (props: Props): React.ReactElement<Props> {
const { className, defaultValue: { value }, isDisabled, isError, label, onEnter, onEscape, style, withLabel } = props;
const defaultValue = (value || '').toString();
return (
@ -35,7 +32,7 @@ function Text (props: Props): React.ReactElement<Props> {
isDisabled={isDisabled}
isError={isError}
label={label}
onChange={onChange(props)}
onChange={_onChange}
onEnter={onEnter}
onEscape={onEscape}
placeholder='<any string>'

View File

@ -4,7 +4,7 @@
import { Props } from '../types';
import React from 'react';
import React, { useCallback } from 'react';
import { ClassOf } from '@polkadot/types';
import { registry } from '@polkadot/react-api';
import { Dropdown } from '@polkadot/react-components';
@ -26,17 +26,16 @@ export const textMap = options.reduce((textMap, { text, value }): TextMap => {
return textMap;
}, {} as unknown as TextMap);
function onChange ({ onChange }: Props): (_: number) => void {
return function (value: number): void {
onChange && onChange({
isValid: true,
value
});
};
}
function VoteThresholdParam ({ className, defaultValue: { value }, isDisabled, isError, label, onChange, style, withLabel }: Props): React.ReactElement<Props> {
const _onChange = useCallback(
(value: number) =>
onChange && onChange({
isValid: true,
value
}),
[onChange]
);
function VoteThresholdParam (props: Props): React.ReactElement<Props> {
const { className, defaultValue: { value }, isDisabled, isError, label, style, withLabel } = props;
const defaultValue = value instanceof ClassOf(registry, 'VoteThreshold')
? value.toNumber()
: bnToBn(value as number).toNumber();
@ -52,7 +51,7 @@ function VoteThresholdParam (props: Props): React.ReactElement<Props> {
isDisabled={isDisabled}
isError={isError}
label={label}
onChange={onChange(props)}
onChange={_onChange}
options={options}
withLabel={withLabel}
/>