Unverified Commit ed08afe9 authored by Kyle Keating's avatar Kyle Keating Committed by GitHub

Improve typechecking on several store util modules (#2299)

parent 3adfcb2e
......@@ -23,15 +23,19 @@ import { createReducer, bindSelectors } from './util';
* the store.
*
* @param {Object[]} modules
* @param {any[]} initArgs - Arguments to pass to each state module's `init` function
* @param [any[]] middleware - List of additional Redux middlewares to use.
* @param {any[]} [initArgs] - Arguments to pass to each state module's `init` function
* @param {any[]} [middleware] - List of additional Redux middlewares to use.
*/
export default function createStore(modules, initArgs = [], middleware = []) {
// Create the initial state and state update function.
// Namespaced objects for initial states.
const initialState = {};
// Namespaced reducers from each module.
/**
* Namespaced reducers from each module.
* @type {import("redux").ReducersMapObject} allReducers
*/
const allReducers = {};
// Namespaced selectors from each module.
const allSelectors = {};
......
......@@ -7,6 +7,8 @@
* When enabled, every action that changes application state will be printed
* to the console, along with the application state before and after the action
* was handled.
*
* @param {import("redux").Store} store
*/
export default function debugMiddleware(store) {
/* eslint-disable no-console */
......@@ -14,6 +16,7 @@ export default function debugMiddleware(store) {
return function (next) {
return function (action) {
// @ts-ignore The window interface needs to be expanded to include this property
if (!window.debug) {
next(action);
return;
......@@ -29,7 +32,7 @@ export default function debugMiddleware(store) {
next(action);
console.log('Next State:', store.getState());
console.groupEnd(groupTitle);
console.groupEnd();
};
};
/* eslint-enable no-console */
......
......@@ -6,6 +6,17 @@ import shallowEqual from 'shallowequal';
import warnOnce from '../../shared/warn-once';
import { useService } from '../util/service-context';
/**
* @typedef {import("redux").Store} Store
*/
/**
* @template T
* @callback StoreCallback
* @param {Store} store
* @return {T}
*/
/**
* Hook for accessing state or actions from the store inside a component.
*
......@@ -30,7 +41,7 @@ import { useService } from '../util/service-context';
* }
*
* @template T
* @param {Function} callback -
* @param {StoreCallback<T>} callback -
* Callback that receives the store as an argument and returns some state
* and/or actions extracted from the store.
* @return {T} - The result of `callback(store)`
......@@ -40,10 +51,10 @@ export default function useStore(callback) {
// Store the last-used callback in a ref so we can access it in the effect
// below without having to re-subscribe to the store when it changes.
const lastCallback = useRef(null);
const lastCallback = useRef(/** @type {StoreCallback<T>|null} */ (null));
lastCallback.current = callback;
const lastResult = useRef(null);
const lastResult = useRef(/** @type {T|undefined} */ (undefined));
lastResult.current = callback(store);
// Check for a performance issue caused by `callback` returning a different
......@@ -58,6 +69,7 @@ export default function useStore(callback) {
}
// Abuse `useReducer` to force updates when the store state changes.
const [, forceUpdate] = useReducer(x => x + 1, 0);
// Connect to the store, call `callback(store)` whenever the store changes
......@@ -69,7 +81,8 @@ export default function useStore(callback) {
return;
}
lastResult.current = result;
forceUpdate();
// Force this function to ignore parameters and just force a store update.
/** @type {()=>any} */ (forceUpdate)();
}
// Check for any changes since the component was rendered.
......
......@@ -8,6 +8,10 @@
* https://reactjs.org/docs/hooks-reference.html#usecontext
*/
/**
* @typedef {import("redux").Store} Store
*/
import { createContext, createElement } from 'preact';
import { useContext } from 'preact/hooks';
......@@ -103,6 +107,7 @@ export function withServices(Component) {
* context of custom hooks.
*
* @param {string} service - Name of the service to look up
* @return {Object}
*/
export function useService(service) {
const injector = useContext(ServiceContext);
......
......@@ -20,7 +20,13 @@
"sidebar/*.js",
"sidebar/store/modules/*.js",
"sidebar/services/*.js",
"sidebar/util/*.js"
"sidebar/util/*.js",
// TODO replace these with sidebar/store/* when all modules are converted
"sidebar/store/create-store.js",
"sidebar/store/debug-middleware.js",
"sidebar/store/use-store.js",
],
"exclude": [
// Enable this once the rest of `src/sidebar` is checked.
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment