react-redux#useStore TypeScript Examples

The following examples show how to use react-redux#useStore. 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: index.tsx    From datart with Apache License 2.0 6 votes vote down vote up
useInjectReducer = ({ key, reducer }: InjectReducerParams) => {
  const store = useStore();

  const isInjected = React.useRef(false);

  if (!isInjected.current) {
    getInjectors(store).injectReducer(key, reducer);
    isInjected.current = true;
  }
}
Example #2
Source File: DragndropPostList.tsx    From clearflask with Apache License 2.0 5 votes vote down vote up
DragndropPostListPostListInner = React.memo((props: {
  PostListProps: React.ComponentProps<typeof PostList>;
  dragSelectedTourAnchorProps?: React.ComponentProps<typeof TourAnchor>;
}) => {
  const theme = useTheme();
  const store = useStore();
  return (
    <PostList
      {...props.PostListProps}
      PanelPostProps={{
        margins: theme.spacing(DashboardListPostSpacing, DashboardListPostSpacing, DashboardListPostSpacing, DashboardListPostSpacing + 1),
        ...props.PostListProps.PanelPostProps,
        wrapPost: (post, content, index) => (
          <Draggable
            draggableId={post.ideaId}
            index={index}
          >
            {(providedDraggable, snapshotDraggable) => {
              var inner = content;
              if (props.dragSelectedTourAnchorProps) {
                if (!!props.PostListProps.selected && lastSelectedId !== props.PostListProps.selected) {
                  lastSelectedId = props.PostListProps.selected;
                }
                if (lastSelectedId === post.ideaId) {
                  inner = (
                    <Provider store={ServerAdmin.get().getStore()}>
                      <TourAnchor placement='top' {...props.dragSelectedTourAnchorProps} zIndex={zb => zb.modal - 1}>
                        <Provider store={store}>
                          {inner}
                        </Provider>
                      </TourAnchor>
                    </Provider>
                  );
                }
              }
              inner = (
                <DragndropPostListDraggableInner
                  providedDraggable={providedDraggable}
                  isDragging={snapshotDraggable.isDragging}
                  draggingOver={snapshotDraggable.draggingOver}
                  dropAnimation={snapshotDraggable.dropAnimation}
                  content={inner}
                />
              );
              return inner as any;
            }}
          </Draggable>
        ),
      }}
    />
  );
}, customReactMemoEquals({ nested: new Set(['dragSelectedTourAnchorProps', 'PostListProps']) }))
Example #3
Source File: useConnector.ts    From reactant with MIT License 5 votes vote down vote up
/**
 * ## Description
 *
 * `useConnector` is a React Hooks, which you can use to inject any shared state and derived data that you want to render using.
 * And it supports both `useConnector(() => this.renderPropsValue)` and `useConnector(() => this.getMapStateToProps())` uses.
 *
 * ## Example
 *
 * ```tsx
 * @injectable()
 * class FooView extends ViewModule {
 *   @state
 *   key = 'str';
 *
 *   @action
 *   setValue(value: any) {
 *     this.key = value;
 *   }
 *
 *   component() {
 *     const { key } = useConnector(() => ({ key: this.key }));
 *     // or `const key = useConnector(() => this.key);`
 *     return <span>{key}</span>;
 *   }
 * }
 *
 * const container = document.createElement('div');
 * document.body.appendChild(container);
 *
 * act(() => {
 *   createApp({
 *     modules: [],
 *     main: FooView,
 *     render,
 *   }).bootstrap(container);
 * });
 *
 * expect(container.querySelector('span')?.textContent).toBe('str');
 * ```
 */
export function useConnector<T>(
  selector: () => T,
  shallowEqual?: ShallowEqual
) {
  try {
    return useSelector(
      selector,
      shallowEqual || areShallowEqualWithObject
    ) as T;
  } catch (e) {
    try {
      useStore();
    } catch (error) {
      console.error(`No class with a field decorated by '@state' is injected.`);
      throw e;
    }
    throw e;
  }
}
Example #4
Source File: IdeApp.tsx    From kliveide with MIT License 4 votes vote down vote up
IdeApp: React.VFC = () => {
  // --- Let's use the store for dispatching actions
  const store = useStore();
  const dispatch = useDispatch();

  // --- Component state (changes of them triggers re-rendering)
  const [themeStyle, setThemeStyle] = useState<CSSProperties>({});
  const [themeClass, setThemeClass] = useState("");
  const ideLoaded = useSelector((s: AppState) => s.ideUiLoaded);
  const showStatusBar = useSelector(
    (s: AppState) => s.emuViewOptions.showStatusBar
  );
  const showSidebar = useSelector(
    (s: AppState) => s.emuViewOptions.showSidebar
  );
  const showToolFrame = useSelector((s: AppState) => s.toolFrame.visible);
  const showDocuments = useSelector(
    (s: AppState) => !s.toolFrame.visible || !s.toolFrame.maximized
  );
  const mounted = useRef(false);

  useEffect(() => {
    const themeService = getThemeService();
    // --- State change event handlers
    const isWindowsChanged = (isWindows: boolean) => {
      themeService.isWindows = isWindows;
      updateThemeState();
    };
    const themeChanged = (theme: string) => {
      themeService.setTheme(theme);
      updateThemeState();
    };

    if (!mounted.current) {
      // --- Mount logic, executed only once during the app's life cycle
      mounted.current = true;
      updateThemeState();

      getStore().themeChanged.on(themeChanged);
      getStore().isWindowsChanged.on(isWindowsChanged);

      // --- Set up activities
    }
    return () => {
      // --- Unsubscribe
      getStore().isWindowsChanged.off(isWindowsChanged);
      getStore().themeChanged.off(themeChanged);
      mounted.current = false;
    };
  }, [store]);

  // --- Apply styles to body so that dialogs, context menus can use it, too.
  document.body.setAttribute("style", toStyleString(themeStyle));
  document.body.setAttribute("class", themeClass);

  return (
    <>
      {ideLoaded && (
        <Fill id="klive_ide_app">
          <Row>
            <Column width={48}>
              <ActivityBar />
            </Column>
            <SplitPanel
              splitterSize={4}
              horizontal={true}
              panel1MinSize={MIN_SIDEBAR_WIDTH}
              panel2MinSize={MIN_DESK_WIDTH}
              initialSize={"20%"}
              panel1={<SideBar />}
              showPanel1={showSidebar}
              panel2={
                <SplitPanel
                  splitterSize={4}
                  horizontal={false}
                  reverse={true}
                  panel1MinSize={MIN_TOOL_HEIGHT}
                  showPanel1={showToolFrame}
                  panel1={<ToolFrame />}
                  panel2MinSize={MIN_DESK_HEIGHT}
                  showPanel2={showDocuments}
                  panel2={<IdeDocumentFrame />}
                  initialSize="33%"
                />
              }
            />
          </Row>
          <Row
            height="fittoclient"
            style={{ display: showStatusBar ? undefined : "none" }}
          >
            <IdeStatusbar />
          </Row>
          <IdeContextMenu target="#klive_ide_app" />
          <ModalDialog targetId="#app" />
        </Fill>
      )}
    </>
  );

  /**
   * Updates the current theme to dislay the app
   * @returns
   */
  function updateThemeState(): void {
    const themeService = getThemeService();
    const theme = themeService.getActiveTheme();
    if (!theme) {
      return;
    }
    setThemeStyle(themeService.getThemeStyle());
    setThemeClass(`app-container ${theme.name}-theme`);
  }
}
Example #5
Source File: App.tsx    From polkabtc-ui with Apache License 2.0 4 votes vote down vote up
function App(): JSX.Element {
  const polkaBtcLoaded = useSelector((state: StoreType) => state.general.polkaBtcLoaded);
  const address = useSelector((state: StoreType) => state.general.address);
  const [isLoading, setIsLoading] = React.useState(true);
  const dispatch = useDispatch();
  const store = useStore();

  // Load the main PolkaBTC API - connection to the PolkaBTC bridge
  const loadPolkaBTC = React.useCallback(async (): Promise<void> => {
    try {
      window.polkaBTC = await connectToParachain();
      dispatch(isPolkaBtcLoaded(true));
      setIsLoading(false);
    } catch (error) {
      toast.warn('Unable to connect to the BTC-Parachain.');
      console.log('Unable to connect to the BTC-Parachain.');
      console.log('error.message => ', error.message);
    }

    try {
      startFetchingLiveData(dispatch, store);
    } catch (error) {
      console.log('Error fetching live data.');
      console.log('error.message => ', error.message);
    }
  }, [
    dispatch,
    store
  ]);

  // Load the connection to the faucet - only for testnet purposes
  const loadFaucet = React.useCallback(async (): Promise<void> => {
    try {
      window.faucet = new FaucetClient(constants.FAUCET_URL);
      dispatch(isFaucetLoaded(true));
    } catch (error) {
      console.log('Unable to connect to the faucet.');
      console.log('error.message => ', error.message);
    }
  }, [
    dispatch
  ]);

  React.useEffect(() => {
    if (!polkaBtcLoaded) return;
    if (!address) return;

    const id = window.polkaBTC.api.createType(ACCOUNT_ID_TYPE_NAME, address);

    // Maybe load the vault client - only if the current address is also registered as a vault
    (async () => {
      try {
        dispatch(isVaultClientLoaded(false));
        const vault = await window.polkaBTC.vaults.get(id);
        dispatch(isVaultClientLoaded(!!vault));
      } catch (error) {
        // TODO: should add error handling
        console.log('No PolkaBTC vault found for the account in the connected Polkadot wallet.');
        console.log('error.message => ', error.message);
      }
    })();

    // Maybe load the staked relayer client - only if the current address is also registered as a vault
    (async () => {
      try {
        dispatch(isStakedRelayerLoaded(false));
        const stakedRelayers = await window.polkaBTC.stakedRelayer.list();
        dispatch(isStakedRelayerLoaded(stakedRelayers.includes(id)));
      } catch (error) {
        // TODO: should add error handling
        console.log('No PolkaBTC staked relayer found for the account in the connected Polkadot wallet.');
        console.log('error.message => ', error.message);
      }
    })();
  }, [
    polkaBtcLoaded,
    address,
    dispatch
  ]);

  React.useEffect(() => {
    // Do not load data if showing static landing page only
    if (checkStaticPage()) return;
    if (!polkaBtcLoaded) return;

    // Initialize data on app bootstrap
    (async () => {
      try {
        const [
          totalPolkaBTC,
          totalLockedDOT,
          btcRelayHeight,
          bitcoinHeight,
          state
        ] = await Promise.all([
          window.polkaBTC.treasury.total(),
          window.polkaBTC.collateral.totalLocked(),
          window.polkaBTC.btcRelay.getLatestBlockHeight(),
          window.polkaBTC.electrsAPI.getLatestBlockHeight(),
          window.polkaBTC.stakedRelayer.getCurrentStateOfBTCParachain()
        ]);

        const parachainStatus = (state: StatusCode) => {
          if (state.isError) {
            return ParachainStatus.Error;
          } else if (state.isRunning) {
            return ParachainStatus.Running;
          } else if (state.isShutdown) {
            return ParachainStatus.Shutdown;
          } else {
            return ParachainStatus.Loading;
          }
        };

        dispatch(
          initGeneralDataAction(
            displayBtcAmount(totalPolkaBTC),
            displayDotAmount(totalLockedDOT),
            Number(btcRelayHeight),
            bitcoinHeight,
            parachainStatus(state)
          )
        );
      } catch (error) {
        // TODO: should have error handling instead of console
        console.log(error);
      }
    })();
  }, [
    dispatch,
    polkaBtcLoaded
  ]);

  // Loads the address for the currently select account and maybe loads the vault and staked relayer dashboards
  React.useEffect(() => {
    if (checkStaticPage()) return; // Do not load data if showing static landing page only
    if (!polkaBtcLoaded) return;

    (async () => {
      const theExtensions = await web3Enable(APP_NAME);
      if (theExtensions.length === 0) return;

      dispatch(setInstalledExtensionAction(theExtensions.map(extension => extension.name)));

      const accounts = await web3Accounts();
      if (accounts.length === 0) {
        dispatch(changeAddressAction(''));
        return;
      }

      const matchedAccount = accounts.find(account => account.address === address);
      const newAddress = matchedAccount ? address : accounts[0].address;

      const { signer } = await web3FromAddress(newAddress);
      // TODO: could store the active address just in one place (either in `window` object or in redux)
      window.polkaBTC.setAccount(newAddress, signer);
      dispatch(changeAddressAction(newAddress));
    })();
  }, [
    address,
    polkaBtcLoaded,
    dispatch
  ]);

  // Loads the PolkaBTC bridge and the faucet
  React.useEffect(() => {
    // Do not load data if showing static landing page only
    if (checkStaticPage()) return;
    if (polkaBtcLoaded) return;

    (async () => {
      try {
        // TODO: should avoid any race condition
        setTimeout(() => {
          if (isLoading) setIsLoading(false);
        }, 3000);
        await loadPolkaBTC();
        await loadFaucet();
        keyring.loadAll({});
      } catch (error) {
        console.log(error.message);
      }
    })();
    startFetchingLiveData(dispatch, store);
  }, [
    loadPolkaBTC,
    loadFaucet,
    isLoading,
    polkaBtcLoaded,
    dispatch,
    store
  ]);

  return (
    <>
      <ToastContainer
        position='top-right'
        autoClose={5000}
        hideProgressBar={false} />
      <Layout>
        <LazyLoadingErrorBoundary>
          <Route
            render={({ location }) => {
              if (checkStaticPage()) {
                const pageURLs = [
                  PAGES.stakedRelayer,
                  PAGES.vaults,
                  PAGES.challenges,
                  PAGES.parachain,
                  PAGES.oracles,
                  PAGES.issue,
                  PAGES.redeem,
                  PAGES.relay,
                  PAGES.dashboard,
                  PAGES.vault,
                  PAGES.feedback,
                  PAGES.application
                ];

                for (const pageURL of pageURLs) {
                  if (matchPath(location.pathname, { path: pageURL })) {
                    return <Redirect to={PAGES.home} />;
                  }
                }
              }

              return (
                // TODO: block for now
                // <TransitionWrapper location={location}>
                // TODO: should use loading spinner instead of `Loading...`
                <React.Suspense fallback={<div>Loading...</div>}>
                  <Switch location={location}>
                    <Route path={PAGES.stakedRelayer}>
                      <StakedRelayer />
                    </Route>
                    <Route path={PAGES.vaults}>
                      <VaultsDashboard />
                    </Route>
                    <Route path={PAGES.challenges}>
                      <Challenges />
                    </Route>
                    <Route path={PAGES.parachain}>
                      <ParachainDashboard />
                    </Route>
                    <Route path={PAGES.oracles}>
                      <OraclesDashboard />
                    </Route>
                    <Route path={PAGES.issue}>
                      <IssueRequests />
                    </Route>
                    <Route path={PAGES.redeem}>
                      <RedeemRequests />
                    </Route>
                    <Route path={PAGES.relay}>
                      <RelayDashboard />
                    </Route>
                    <Route path={PAGES.dashboard}>
                      <Dashboard />
                    </Route>
                    <Route path={PAGES.vault}>
                      <VaultDashboard />
                    </Route>
                    <Route path={PAGES.feedback}>
                      <Feedback />
                    </Route>
                    <Route
                      exact
                      path={PAGES.application}>
                      <Application />
                    </Route>
                    <Route
                      path={PAGES.home}
                      exact>
                      <LandingPage />
                    </Route>
                    <Route path='*'>
                      <NoMatch />
                    </Route>
                  </Switch>
                </React.Suspense>
                // </TransitionWrapper>
              );
            }} />
        </LazyLoadingErrorBoundary>
      </Layout>
    </>
  );
}
Example #6
Source File: reimburse-view.tsx    From polkabtc-ui with Apache License 2.0 4 votes vote down vote up
export default function ReimburseView(props: ReimburseViewProps): ReactElement {
  const [isReimbursePending, setReimbursePending] = useState(false);
  const [isRetryPending, setRetryPending] = useState(false);
  const { polkaBtcLoaded, prices } = useSelector((state: StoreType) => state.general);
  const [punishmentDOT, setPunishmentDOT] = useState(new Big(0));
  const [amountDOT, setAmountDOT] = useState(new Big(0));
  const dispatch = useDispatch();
  const store = useStore();
  const { t } = useTranslation();

  useEffect(() => {
    const fetchData = async () => {
      if (!polkaBtcLoaded) return;
      try {
        const [punishment, btcDotRate] = await Promise.all([
          window.polkaBTC.vaults.getPunishmentFee(),
          window.polkaBTC.oracle.getExchangeRate()
        ]);
        const amountPolkaBTC = props.request ? new Big(props.request.amountPolkaBTC) : new Big(0);
        setAmountDOT(amountPolkaBTC.mul(btcDotRate));
        setPunishmentDOT(amountPolkaBTC.mul(btcDotRate).mul(new Big(punishment)));
      } catch (error) {
        console.log(error);
      }
    };

    fetchData();
  }, [props.request, polkaBtcLoaded]);

  const onRetry = async () => {
    if (!polkaBtcLoaded) return;
    setRetryPending(true);
    try {
      if (!props.request) return;
      const redeemId = window.polkaBTC.api.createType('H256', '0x' + props.request.id);
      await window.polkaBTC.redeem.cancel(redeemId, false);
      dispatch(retryRedeemRequestAction(props.request.id));
      await fetchBalances(dispatch, store);
      props.onClose();
      toast.success(t('redeem_page.successfully_cancelled_redeem'));
    } catch (error) {
      console.log(error);
    }
    setRetryPending(false);
  };

  const onBurn = async () => {
    if (!polkaBtcLoaded) return;
    setReimbursePending(true);
    try {
      if (!props.request) return;
      const redeemId = window.polkaBTC.api.createType('H256', '0x' + props.request.id);
      await window.polkaBTC.redeem.cancel(redeemId, true);
      dispatch(reimburseRedeemRequestAction(props.request.id));
      await fetchBalances(dispatch, store);
      props.onClose();
    } catch (error) {
      console.log(error);
    }
    setReimbursePending(false);
  };

  return (
    <React.Fragment>
      <div className='row mt-3'>
        <div className='col reimburse-title'>
          <p className='mb-4'>
            <i className='fas fa-exclamation-circle'></i> &nbsp;
            {t('redeem_page.sorry_redeem_failed')}
          </p>
        </div>
      </div>
      <div className='row justify-center mt-4'>
        <div className='col-9 reimburse-send'>
          {t('redeem_page.vault_did_not_send')}
          <span>{punishmentDOT.toFixed(2).toString()} DOT </span>&nbsp; (~${' '}
          {getUsdAmount(punishmentDOT.toString(), prices.polkadot.usd)})&nbsp;
          {t('redeem_page.compensation')}
        </div>
      </div>
      <div className='row justify-center'>
        <div className='col-9 to-redeem'>
          <p className='mb-4'>{t('redeem_page.to_redeem_polkabtc')}</p>
        </div>
      </div>
      <div className='row justify-center'>
        <div className='col-9 receive-compensation'>
          {t('redeem_page.receive_compensation')}
          <span>{punishmentDOT.toFixed(2)} DOT</span> &nbsp;
          {t('redeem_page.retry_with_another', {
            compensationPrice: getUsdAmount(punishmentDOT.toString(), prices.polkadot.usd)
          })}
        </div>
      </div>
      <div className='row justify-center'>
        <div className='col-6 retry'>
          <ButtonMaybePending
            className='btn green-button app-btn'
            disabled={isRetryPending || isReimbursePending}
            isPending={isRetryPending}
            onClick={onRetry}>
            {t('retry')}
          </ButtonMaybePending>
        </div>
      </div>

      <div className='row justify-center mt-4'>
        <div className='col-10 burn-desc'>
          {t('redeem_page.burn_polkabtc')}
          <span>{amountDOT.toFixed(5).toString()} DOT</span> &nbsp;
          {t('redeem_page.with_added', {
            amountPrice: getUsdAmount(amountDOT.toString(), prices.polkadot.usd)
          })}
          <span>{punishmentDOT.toFixed(5).toString()} DOT</span> &nbsp;
          {t('redeem_page.as_compensation_instead', {
            compensationPrice: getUsdAmount(punishmentDOT.toString(), prices.polkadot.usd)
          })}
        </div>
      </div>

      <div className='row justify-center'>
        <div className='col-6 burn'>
          <Button
            variant='btn red-button app-btn'
            onClick={onBurn}>
            {t('redeem_page.burn')}
          </Button>
        </div>
      </div>
    </React.Fragment>
  );
}