mirror of
https://github.com/pybricks/pybricks-code.git
synced 2026-09-12 17:45:22 +00:00
reducers: use typed useSelector hook
This refactors the code to use a typed useSelector() hook.
This commit is contained in:
+4
-4
@@ -3,10 +3,10 @@
|
||||
|
||||
import { Classes } from '@blueprintjs/core';
|
||||
import React, { useEffect, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import SplitterLayout from 'react-splitter-layout';
|
||||
import Editor from '../editor/Editor';
|
||||
import { RootState } from '../reducers';
|
||||
import { useSelector } from '../reducers';
|
||||
import { toggleBoolean } from '../settings/actions';
|
||||
import { BooleanSettingId } from '../settings/defaults';
|
||||
import StatusBar from '../status-bar/StatusBar';
|
||||
@@ -122,8 +122,8 @@ const Docs: React.FunctionComponent = (_props) => {
|
||||
};
|
||||
|
||||
const App: React.FunctionComponent = (_props) => {
|
||||
const darkMode = useSelector((s: RootState): boolean => s.settings.darkMode);
|
||||
const showDocs = useSelector((s: RootState): boolean => s.settings.showDocs);
|
||||
const darkMode = useSelector((s): boolean => s.settings.darkMode);
|
||||
const showDocs = useSelector((s): boolean => s.settings.showDocs);
|
||||
const [isDragging, setIsDragging] = useState(false);
|
||||
|
||||
// darkMode class has to be applied to body element, otherwise it won't
|
||||
|
||||
@@ -12,10 +12,10 @@ import tomorrowNightEightiesTheme from 'monaco-themes/themes/Tomorrow-Night-Eigh
|
||||
import xcodeTheme from 'monaco-themes/themes/Xcode_default.json';
|
||||
import React, { useEffect, useRef } from 'react';
|
||||
import MonacoEditor, { monaco } from 'react-monaco-editor';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { IDisposable } from 'xterm';
|
||||
import { compile } from '../mpy/actions';
|
||||
import { RootState } from '../reducers';
|
||||
import { useSelector } from '../reducers';
|
||||
import { toggleBoolean } from '../settings/actions';
|
||||
import { BooleanSettingId } from '../settings/defaults';
|
||||
import { isMacOS } from '../utils/os';
|
||||
@@ -63,7 +63,7 @@ const xcodeId = 'xcode';
|
||||
monaco.editor.defineTheme(xcodeId, xcodeTheme as monaco.editor.IStandaloneThemeData);
|
||||
|
||||
const contextMenu = (_props: ContextMenu2ContentProps): JSX.Element => {
|
||||
const editor = useSelector((state: RootState) => state.editor.current);
|
||||
const editor = useSelector((s) => s.editor.current);
|
||||
|
||||
const [i18n] = useI18n({ id: 'editor', translations: { en }, fallback: en });
|
||||
|
||||
@@ -143,7 +143,7 @@ const Editor: React.FunctionComponent = (_props) => {
|
||||
return () => window.removeEventListener('storage', onStorage);
|
||||
});
|
||||
|
||||
const darkMode = useSelector((state: RootState) => state.settings.darkMode);
|
||||
const darkMode = useSelector((s) => s.settings.darkMode);
|
||||
|
||||
const [i18n] = useI18n({ id: 'editor', translations: { en }, fallback: en });
|
||||
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// Copyright (c) 2020-2021 The Pybricks Authors
|
||||
|
||||
import React from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import * as notificationActions from '../notifications/actions';
|
||||
import { RootState } from '../reducers';
|
||||
import { useSelector } from '../reducers';
|
||||
import OpenFileButton, { OpenFileButtonProps } from '../toolbar/OpenFileButton';
|
||||
import { TooltipId } from '../toolbar/i18n';
|
||||
import * as editorActions from './actions';
|
||||
@@ -13,7 +13,7 @@ import openIcon from './open.svg';
|
||||
type OpenButtonProps = Pick<OpenFileButtonProps, 'id'>;
|
||||
|
||||
const OpenButton: React.FunctionComponent<OpenButtonProps> = (props) => {
|
||||
const editor = useSelector((state: RootState) => state.editor.current);
|
||||
const editor = useSelector((s) => s.editor.current);
|
||||
const dispatch = useDispatch();
|
||||
|
||||
return (
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
// Copyright (c) 2020-2021 The Pybricks Authors
|
||||
|
||||
import React from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import * as editorActions from '../editor/actions';
|
||||
import { RootState } from '../reducers';
|
||||
import { useSelector } from '../reducers';
|
||||
import ActionButton, { ActionButtonProps } from '../toolbar/ActionButton';
|
||||
import { TooltipId } from '../toolbar/i18n';
|
||||
import downloadIcon from './save.svg';
|
||||
@@ -13,7 +13,7 @@ type SaveAsButtonProps = Pick<ActionButtonProps, 'id'> &
|
||||
Pick<ActionButtonProps, 'keyboardShortcut'>;
|
||||
|
||||
const SaveAsButton: React.FunctionComponent<SaveAsButtonProps> = (props) => {
|
||||
const editor = useSelector((state: RootState) => state.editor.current);
|
||||
const editor = useSelector((s) => s.editor.current);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
// Copyright (c) 2020-2021 The Pybricks Authors
|
||||
|
||||
import React from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { BleConnectionState } from '../ble/reducers';
|
||||
import { BootloaderConnectionState } from '../lwp3-bootloader/reducers';
|
||||
import * as notificationActions from '../notifications/actions';
|
||||
import { RootState } from '../reducers';
|
||||
import { useSelector } from '../reducers';
|
||||
import OpenFileButton, { OpenFileButtonProps } from '../toolbar/OpenFileButton';
|
||||
import { TooltipId } from '../toolbar/i18n';
|
||||
import { flashFirmware } from './actions';
|
||||
@@ -15,12 +15,10 @@ import firmwareIcon from './firmware.svg';
|
||||
type FlashButtonProps = Pick<OpenFileButtonProps, 'id'>;
|
||||
|
||||
const FlashButton: React.FunctionComponent<FlashButtonProps> = (props) => {
|
||||
const bootloaderConnection = useSelector(
|
||||
(state: RootState) => state.bootloader.connection,
|
||||
);
|
||||
const bleConnection = useSelector((state: RootState) => state.ble.connection);
|
||||
const flashing = useSelector((state: RootState) => state.firmware.flashing);
|
||||
const progress = useSelector((state: RootState) => state.firmware.progress);
|
||||
const bootloaderConnection = useSelector((s) => s.bootloader.connection);
|
||||
const bleConnection = useSelector((s) => s.ble.connection);
|
||||
const flashing = useSelector((s) => s.firmware.flashing);
|
||||
const progress = useSelector((s) => s.firmware.progress);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
// Copyright (c) 2020-2021 The Pybricks Authors
|
||||
|
||||
import React from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { toggleBluetooth } from '../ble/actions';
|
||||
import { BleConnectionState } from '../ble/reducers';
|
||||
import { BootloaderConnectionState } from '../lwp3-bootloader/reducers';
|
||||
import { RootState } from '../reducers';
|
||||
import { useSelector } from '../reducers';
|
||||
import ActionButton, { ActionButtonProps } from '../toolbar/ActionButton';
|
||||
import { TooltipId } from '../toolbar/i18n';
|
||||
import btConnectedIcon from './bt-connected.svg';
|
||||
@@ -15,10 +15,8 @@ import btDisconnectedIcon from './bt-disconnected.svg';
|
||||
type BluetoothButtonProps = Pick<ActionButtonProps, 'id'>;
|
||||
|
||||
const BluetoothButton: React.FunctionComponent<BluetoothButtonProps> = (props) => {
|
||||
const bootloaderConnection = useSelector(
|
||||
(state: RootState) => state.bootloader.connection,
|
||||
);
|
||||
const bleConnection = useSelector((state: RootState) => state.ble.connection);
|
||||
const bootloaderConnection = useSelector((s) => s.bootloader.connection);
|
||||
const bleConnection = useSelector((s) => s.ble.connection);
|
||||
|
||||
const isDisconnected =
|
||||
bootloaderConnection === BootloaderConnectionState.Disconnected &&
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// Copyright (c) 2020-2021 The Pybricks Authors
|
||||
|
||||
import React from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { RootState } from '../reducers';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useSelector } from '../reducers';
|
||||
import ActionButton, { ActionButtonProps } from '../toolbar/ActionButton';
|
||||
import { TooltipId } from '../toolbar/i18n';
|
||||
import { downloadAndRun } from './actions';
|
||||
@@ -14,11 +14,9 @@ type RunButtonProps = Pick<ActionButtonProps, 'id'> &
|
||||
Pick<ActionButtonProps, 'keyboardShortcut'>;
|
||||
|
||||
const RunButton: React.FunctionComponent<RunButtonProps> = (props) => {
|
||||
const editor = useSelector((state: RootState) => state.editor.current);
|
||||
const downloadProgress = useSelector(
|
||||
(state: RootState) => state.hub.downloadProgress,
|
||||
);
|
||||
const runtime = useSelector((state: RootState) => state.hub.runtime);
|
||||
const editor = useSelector((s) => s.editor.current);
|
||||
const downloadProgress = useSelector((s) => s.hub.downloadProgress);
|
||||
const runtime = useSelector((s) => s.hub.runtime);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
|
||||
@@ -2,8 +2,8 @@
|
||||
// Copyright (c) 2020-2021 The Pybricks Authors
|
||||
|
||||
import React from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { RootState } from '../reducers';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { useSelector } from '../reducers';
|
||||
import ActionButton, { ActionButtonProps } from '../toolbar/ActionButton';
|
||||
import { TooltipId } from '../toolbar/i18n';
|
||||
import { stop } from './actions';
|
||||
@@ -14,7 +14,7 @@ type StopButtonProps = Pick<ActionButtonProps, 'id'> &
|
||||
Pick<ActionButtonProps, 'keyboardShortcut'>;
|
||||
|
||||
const StopButton: React.FunctionComponent<StopButtonProps> = (props) => {
|
||||
const runtime = useSelector((state: RootState) => state.hub.runtime);
|
||||
const runtime = useSelector((s) => s.hub.runtime);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
|
||||
@@ -14,9 +14,9 @@ import {
|
||||
} from '@blueprintjs/core';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { appName } from '../app/constants';
|
||||
import { RootState } from '../reducers';
|
||||
import { useSelector } from '../reducers';
|
||||
import { fetchList, select } from './actions';
|
||||
import { LicenseStringId } from './i18n';
|
||||
import en from './i18n.en.json';
|
||||
@@ -31,7 +31,7 @@ type LicenseListPanelProps = {
|
||||
const LicenseListPanel: React.VoidFunctionComponent<LicenseListPanelProps> = (
|
||||
props,
|
||||
) => {
|
||||
const licenseList = useSelector((state: RootState) => state.licenses.list);
|
||||
const licenseList = useSelector((s) => s.licenses.list);
|
||||
|
||||
return (
|
||||
<div className="pb-license-list">
|
||||
@@ -54,7 +54,7 @@ const LicenseListPanel: React.VoidFunctionComponent<LicenseListPanelProps> = (
|
||||
};
|
||||
|
||||
const LicenseInfoPanel = React.forwardRef<HTMLDivElement>((_props, ref) => {
|
||||
const licenseInfo = useSelector((state: RootState) => state.licenses.selected);
|
||||
const licenseInfo = useSelector((s) => s.licenses.selected);
|
||||
|
||||
const [i18n] = useI18n({ id: 'license', translations: { en }, fallback: en });
|
||||
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
// SPDX-License-Identifier: MIT
|
||||
// Copyright (c) 2020-2021 The Pybricks Authors
|
||||
|
||||
import { TypedUseSelectorHook, useSelector as useReduxSelector } from 'react-redux';
|
||||
import { Reducer, combineReducers } from 'redux';
|
||||
import app from './app/reducers';
|
||||
import ble from './ble/reducers';
|
||||
@@ -31,3 +32,8 @@ export const rootReducer = combineReducers({
|
||||
type StateFromReducer<R> = R extends Reducer<infer S> ? S : never;
|
||||
|
||||
export type RootState = StateFromReducer<typeof rootReducer>;
|
||||
|
||||
/**
|
||||
* Typed version of react-redux useSelector() hook.
|
||||
*/
|
||||
export const useSelector: TypedUseSelectorHook<RootState> = useReduxSelector;
|
||||
|
||||
@@ -19,7 +19,7 @@ import {
|
||||
import { Tooltip2 } from '@blueprintjs/popover2';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useMemo, useState } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import AboutDialog from '../about/AboutDialog';
|
||||
import { checkForUpdate, installPrompt, reload } from '../app/actions';
|
||||
import {
|
||||
@@ -30,7 +30,7 @@ import {
|
||||
tooltipDelay,
|
||||
} from '../app/constants';
|
||||
import { pseudolocalize } from '../i18n';
|
||||
import { RootState } from '../reducers';
|
||||
import { useSelector } from '../reducers';
|
||||
import ExternalLinkIcon from '../utils/ExternalLinkIcon';
|
||||
import { isMacOS } from '../utils/os';
|
||||
import { setBoolean, setString, toggleBoolean } from './actions';
|
||||
@@ -47,31 +47,17 @@ type SettingsProps = {
|
||||
const SettingsDrawer: React.FunctionComponent<SettingsProps> = (props) => {
|
||||
const [isAboutDialogOpen, setIsAboutDialogOpen] = useState(false);
|
||||
|
||||
const showDocs = useSelector((state: RootState) => state.settings.showDocs);
|
||||
const darkMode = useSelector((state: RootState) => state.settings.darkMode);
|
||||
const flashCurrentProgram = useSelector(
|
||||
(state: RootState) => state.settings.flashCurrentProgram,
|
||||
);
|
||||
const serviceWorker = useSelector((state: RootState) => state.app.serviceWorker);
|
||||
const checkingForUpdate = useSelector(
|
||||
(state: RootState) => state.app.checkingForUpdate,
|
||||
);
|
||||
const updateAvailable = useSelector(
|
||||
(state: RootState) => state.app.updateAvailable,
|
||||
);
|
||||
const beforeInstallPrompt = useSelector(
|
||||
(state: RootState) => state.app.beforeInstallPrompt,
|
||||
);
|
||||
const promptingInstall = useSelector(
|
||||
(state: RootState) => state.app.promptingInstall,
|
||||
);
|
||||
const readyForOfflineUse = useSelector(
|
||||
(state: RootState) => state.app.readyForOfflineUse,
|
||||
);
|
||||
const hubName = useSelector((state: RootState) => state.settings.hubName);
|
||||
const isHubNameValid = useSelector(
|
||||
(state: RootState) => state.settings.isHubNameValid,
|
||||
);
|
||||
const showDocs = useSelector((s) => s.settings.showDocs);
|
||||
const darkMode = useSelector((s) => s.settings.darkMode);
|
||||
const flashCurrentProgram = useSelector((s) => s.settings.flashCurrentProgram);
|
||||
const serviceWorker = useSelector((s) => s.app.serviceWorker);
|
||||
const checkingForUpdate = useSelector((s) => s.app.checkingForUpdate);
|
||||
const updateAvailable = useSelector((s) => s.app.updateAvailable);
|
||||
const beforeInstallPrompt = useSelector((s) => s.app.beforeInstallPrompt);
|
||||
const promptingInstall = useSelector((s) => s.app.promptingInstall);
|
||||
const readyForOfflineUse = useSelector((s) => s.app.readyForOfflineUse);
|
||||
const hubName = useSelector((s) => s.settings.hubName);
|
||||
const isHubNameValid = useSelector((s) => s.settings.isHubNameValid);
|
||||
|
||||
const dispatch = useDispatch();
|
||||
|
||||
|
||||
@@ -5,9 +5,8 @@ import { Button, Intent, ProgressBar } from '@blueprintjs/core';
|
||||
import { Classes as Classes2, Popover2, Popover2Props } from '@blueprintjs/popover2';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React from 'react';
|
||||
import { useSelector } from 'react-redux';
|
||||
import { BleConnectionState } from '../ble/reducers';
|
||||
import { RootState } from '../reducers';
|
||||
import { useSelector } from '../reducers';
|
||||
import { MessageId } from './i18n';
|
||||
import en from './i18n.en.json';
|
||||
|
||||
@@ -19,11 +18,9 @@ const commonPopoverProps: Partial<Popover2Props> = {
|
||||
};
|
||||
|
||||
const HubInfoButton: React.VFC = (_props) => {
|
||||
const deviceName = useSelector((state: RootState) => state.ble.deviceName);
|
||||
const deviceType = useSelector((state: RootState) => state.ble.deviceType);
|
||||
const deviceFirmwareVersion = useSelector(
|
||||
(state: RootState) => state.ble.deviceFirmwareVersion,
|
||||
);
|
||||
const deviceName = useSelector((s) => s.ble.deviceName);
|
||||
const deviceType = useSelector((s) => s.ble.deviceType);
|
||||
const deviceFirmwareVersion = useSelector((s) => s.ble.deviceFirmwareVersion);
|
||||
|
||||
const [i18n] = useI18n({ id: 'statusBar', translations: { en }, fallback: en });
|
||||
|
||||
@@ -69,10 +66,8 @@ const HubInfoButton: React.VFC = (_props) => {
|
||||
};
|
||||
|
||||
const BatteryIndicator: React.VFC = (_props) => {
|
||||
const charging = useSelector((state: RootState) => state.ble.deviceBatteryCharging);
|
||||
const lowBatteryWarning = useSelector(
|
||||
(state: RootState) => state.ble.deviceLowBatteryWarning,
|
||||
);
|
||||
const charging = useSelector((s) => s.ble.deviceBatteryCharging);
|
||||
const lowBatteryWarning = useSelector((s) => s.ble.deviceLowBatteryWarning);
|
||||
|
||||
const [i18n] = useI18n({ id: 'statusBar', translations: { en }, fallback: en });
|
||||
|
||||
@@ -102,7 +97,7 @@ const BatteryIndicator: React.VFC = (_props) => {
|
||||
};
|
||||
|
||||
const StatusBar: React.VFC = (_props) => {
|
||||
const connection = useSelector((state: RootState) => state.ble.connection);
|
||||
const connection = useSelector((s) => s.ble.connection);
|
||||
|
||||
return (
|
||||
<div
|
||||
|
||||
@@ -5,10 +5,10 @@ import { Menu, MenuDivider, MenuItem, ResizeSensor } from '@blueprintjs/core';
|
||||
import { ContextMenu2, ContextMenu2ContentProps } from '@blueprintjs/popover2';
|
||||
import { useI18n } from '@shopify/react-i18n';
|
||||
import React, { useContext, useEffect, useMemo, useRef } from 'react';
|
||||
import { useDispatch, useSelector } from 'react-redux';
|
||||
import { useDispatch } from 'react-redux';
|
||||
import { Terminal as XTerm } from 'xterm';
|
||||
import { FitAddon } from 'xterm-addon-fit';
|
||||
import { RootState } from '../reducers';
|
||||
import { useSelector } from '../reducers';
|
||||
import { isMacOS } from '../utils/os';
|
||||
import { TerminalContext } from './TerminalContext';
|
||||
import { receiveData } from './actions';
|
||||
@@ -100,7 +100,7 @@ function createContextMenu(
|
||||
const Terminal: React.FC = (_props) => {
|
||||
const { xterm, fitAddon } = useMemo(createXTerm, [createXTerm]);
|
||||
const terminalRef = useRef<HTMLDivElement>(null);
|
||||
const darkMode = useSelector((state: RootState) => state.settings.darkMode);
|
||||
const darkMode = useSelector((s) => s.settings.darkMode);
|
||||
const dispatch = useDispatch();
|
||||
const terminalStream = useContext(TerminalContext);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user