react#startTransition TypeScript Examples

The following examples show how to use react#startTransition. You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example #1
Source File: useRippleActivationClassName.ts    From sc-translator-crx with GNU General Public License v3.0 6 votes vote down vote up
useRippleActivationClassName = (activationClassName: string, deactivationClassName: string): [string, () => void] => {
    const [className, setClassName] = useState('');

    const clearClassNameTimeoutRef = useRef<ReturnType<typeof setTimeout>>();
    const classNameRef = useRef('');

    const setClassNameWithRef = useCallback((className: string) => {
        setClassName(className);
        classNameRef.current = className;
    }, []);

    const onDeactivate = useCallback(() => {
        clearClassNameTimeoutRef.current = setTimeout(() => {
            setClassNameWithRef(deactivationClassName);

            clearClassNameTimeoutRef.current = setTimeout(() => setClassNameWithRef(''), 200);
        }, 100);

        window.removeEventListener('mouseup', onDeactivate, true);
    }, [deactivationClassName, setClassNameWithRef]);

    const onActivate = useCallback(() => {
        clearClassNameTimeoutRef.current && clearTimeout(clearClassNameTimeoutRef.current);

        classNameRef.current && setClassNameWithRef('');
        startTransition(() => setClassNameWithRef(activationClassName));

        window.addEventListener('mouseup', onDeactivate, true);
    }, [activationClassName, onDeactivate, setClassNameWithRef]);

    return [className, onActivate];
}
Example #2
Source File: index.tsx    From sc-translator-crx with GNU General Public License v3.0 5 votes vote down vote up
SearchField: React.FC<SearchFieldProps> = React.memo(({ onChange }) => {
    const searchElementRef = useRef<HTMLInputElement>(null);

    return (
        <div className='search-field'>
            <Button
                variant='icon'
                onClick={() => {
                    if (!searchElementRef.current) { return; }

                    searchElementRef.current.select();
                }}
            >
                <IconFont
                    iconName='#icon-search'
                    style={{fontSize: '20px'}}
                />
            </Button>
            <input
                type='text'
                ref={searchElementRef}
                defaultValue={''}
                placeholder={getMessage('collectionSearchText')}
                onChange={e => startTransition(() => onChange((e.target as HTMLInputElement).value))}
            />
            <Button
                variant='icon'
                className='search-field__close-btn'
                onClick={() => {
                    if (!searchElementRef.current) { return; }

                    searchElementRef.current.value = '';
                    searchElementRef.current.blur();
                    onChange('');
                }}
            >
                <IconFont
                    iconName='#icon-GoX'
                    style={{fontSize: '20px'}}
                />
            </Button>
        </div>
    );
})
Example #3
Source File: emitter.ts    From sail with Apache License 2.0 5 votes vote down vote up
raiseBatchCacheUpdated(ids: ReadonlySet<string>): void {
    startTransition(() => {
      this._emitter.emit(
        CacheBatchUpdateEvent.type,
        new CacheBatchUpdateEvent(ids)
      );
    });
  }
Example #4
Source File: emitter.ts    From sail with Apache License 2.0 5 votes vote down vote up
raiseCacheCleared(): void {
    startTransition(() => {
      this._emitter.emit(CacheClearEvent.type, new CacheClearEvent());
    });
  }
Example #5
Source File: useAccountsData.ts    From sail with Apache License 2.0 5 votes vote down vote up
useAccountsData = (
  keys: (PublicKey | null | undefined)[]
): readonly AccountDatum[] => {
  const { getDatum, onBatchCache, fetchKeys, onError } = useSail();

  const [data, setData] = useState<{ [cacheKey: string]: AccountDatum }>(() =>
    loadKeysFromCache(getDatum, keys)
  );

  // TODO: add cancellation
  const fetchAndSetKeys = useDebouncedCallback(
    async (
      fetchKeys: FetchKeysFn,
      keys: readonly (PublicKey | null | undefined)[]
    ) => {
      const keysData = await fetchKeysMaybe(fetchKeys, keys);

      const nextData: Record<string, AccountDatum> = {};
      keys.forEach((key, keyIndex) => {
        if (key) {
          const keyData = keysData[keyIndex];
          if (keyData) {
            nextData[getCacheKeyOfPublicKey(key)] = keyData.data;
          } else {
            nextData[getCacheKeyOfPublicKey(key)] = keyData;
          }
        }
      });
      startTransition(() => {
        setData(nextData);
      });
    },
    100
  );

  useEffect(() => {
    void (async () => {
      await fetchAndSetKeys(fetchKeys, keys)?.catch((e) => {
        onError(new SailCacheRefetchError(e, keys));
      });
    })();
  }, [keys, fetchAndSetKeys, fetchKeys, onError]);

  useAccountsSubscribe(keys);

  // refresh from the cache whenever the cache is updated
  useEffect(() => {
    return onBatchCache((e) => {
      if (keys.find((key) => key && e.hasKey(key))) {
        void fetchAndSetKeys(fetchKeys, keys)?.catch((e) => {
          onError(new SailCacheRefetchError(e, keys));
        });
      }
    });
  }, [keys, fetchAndSetKeys, fetchKeys, onError, onBatchCache]);

  // unload debounces when the component dismounts
  useEffect(() => {
    return () => {
      fetchAndSetKeys.cancel();
    };
  }, [fetchAndSetKeys]);

  return useMemo(() => {
    return keys.map((key) => {
      if (key) {
        return data[getCacheKeyOfPublicKey(key)];
      }

      return key;
    });
  }, [data, keys]);
}
Example #6
Source File: useParsedAccountsData.ts    From sail with Apache License 2.0 5 votes vote down vote up
useParsedAccountsData = <T>(
  keys: (PublicKey | null | undefined)[],
  parser: AccountParser<T>
): ParsedAccountDatum<T>[] => {
  const { onError } = useSail();
  const data = useAccountsData(keys);
  const [parsed, setParsed] = useState<Record<string, ParsedAccountDatum<T>>>(
    keys.reduce<Record<string, ParsedAccountDatum<T>>>((acc, k) => {
      if (k) {
        acc[getCacheKeyOfPublicKey(k)] = undefined;
      }

      return acc;
    }, {})
  );

  useEffect(() => {
    startTransition(() => {
      setParsed((prevParsed) => {
        const nextParsed = { ...prevParsed };
        zip(keys, data).forEach(([key, datum]) => {
          if (datum) {
            const key = getCacheKeyOfPublicKey(datum.accountId);
            const prevValue = prevParsed[key];
            if (
              prevValue &&
              prevValue.raw.length === datum.accountInfo.data.length &&
              prevValue.raw.equals(datum.accountInfo.data)
            ) {
              // preserve referential equality if buffers are equal
              return;
            }
            try {
              const parsed = parser(datum);
              nextParsed[key] = {
                ...datum,
                accountInfo: {
                  ...datum.accountInfo,
                  data: parsed,
                },
                raw: datum.accountInfo.data,
              };
            } catch (e) {
              onError(new SailAccountParseError(e, datum));
              nextParsed[key] = null;
              return;
            }
          }
          if (key && datum === null) {
            nextParsed[getCacheKeyOfPublicKey(key)] = null;
          }
        });
        return nextParsed;
      });
    });
  }, [data, keys, onError, parser]);

  return useMemo(() => {
    return keys.map((k) => {
      if (!k) {
        return k;
      }
      return parsed[getCacheKeyOfPublicKey(k)];
    });
  }, [keys, parsed]);
}
Example #7
Source File: index.tsx    From sc-translator-crx with GNU General Public License v3.0 4 votes vote down vote up
LanguageSelect: React.FC<LanguageSelectProps> = ({ value, onChange, className, langCodes, langLocal, recentLangs }) => {
    const [showOptions, setShowOptions] = useState(false);
    const [searchLangCodes, setSearchLangCodes] = useState<LangCodes>([]);
    const [searchText, setSearchText] = useState('');

    const searchInputElementRef = useRef<HTMLInputElement>(null);
    const languageSelectElementRef = useRef<HTMLDivElement>(null);
    const onMouseDownRef = useRef((e: MouseEvent) => {
        const path = e.composedPath?.();

        if (languageSelectElementRef.current && path.indexOf(languageSelectElementRef.current) >= 0) { return; }

        setShowOptions(false);
    });

    const handleOptionClick = useCallback((value: string) => {
        onChange(value);
        setShowOptions(false);
    }, [onChange]);

    const handleInputChange = useCallback(() => {
        if (!searchInputElementRef.current) { return; }

        setSearchText(searchInputElementRef.current.value);
    }, []);

    const handleOptionsShow = useCallback(() => {
        if (!searchInputElementRef.current) { return; }

        const tempElement = searchInputElementRef.current.parentElement?.parentElement?.parentElement;
        tempElement && (tempElement.scrollTop = 0);
        searchInputElementRef.current.focus();
        searchInputElementRef.current.select();
    }, []);

    useEffect(() => {
        startTransition(() => {
            setSearchLangCodes(langCodes.filter(v => v.name.includes(searchText)));
        });
    }, [langCodes, searchText]);

    useEffect(() => {
        showOptions ? window.addEventListener('mousedown', onMouseDownRef.current, true) : window.removeEventListener('mousedown', onMouseDownRef.current, true);
    }, [showOptions]);

    return (
        <div
            className={`language-select${className ? ' ' + className : ''}`}
            ref={languageSelectElementRef}
            tabIndex={-1}
            onClick={() => setShowOptions(v => !v)}
        >
            <span className='language-select__badge'>
                <span className='language-select__badge-text'>{langLocal[value] ?? langLocal['']}</span>
                <IconFont iconName='#icon-GoChevronDown' />
            </span>
            <SelectOptions
                show={showOptions}
                onShow={handleOptionsShow}
                onClick={e => e.stopPropagation()}
            >
                {recentLangs?.map((v) => (v in langLocal && <div
                    className='language-select__option'
                    key={'recent-' + v}
                    onClick={() => handleOptionClick(v)}
                >
                    {langLocal[v]}
                </div>))}
                <div className='language-select__search'>
                    <IconFont iconName='#icon-search' />
                    <div className='language-select__search-input'>
                        <input type='text' placeholder={getMessage('sentenceSearchLanguages')} onChange={handleInputChange} ref={searchInputElementRef} />
                    </div>
                </div>
                {searchLangCodes.length > 0 ? searchLangCodes.map((v) => (<div
                    className='language-select__option'
                    key={v['code']}
                    onClick={() => handleOptionClick(v['code'])}
                >
                    {v['name']}
                </div>)) : <div className='language-select__no-result'>
                    {getMessage('sentenceNoResult')}
                </div>}
            </SelectOptions>
        </div>
    );
}