Skip to content

Commit

Permalink
fix infinite recursion sometimes during React SafeMode
Browse files Browse the repository at this point in the history
  • Loading branch information
arshaw committed Jul 26, 2022
1 parent 5190c33 commit 7f8c109
Show file tree
Hide file tree
Showing 5 changed files with 19 additions and 6 deletions.
2 changes: 1 addition & 1 deletion packages/common/src/main.ts
Expand Up @@ -50,7 +50,7 @@ export {
isArraysEqual,
} from './util/array'

export { memoize, memoizeObjArg, memoizeArraylike, memoizeHashlike } from './util/memoize'
export { memoize, memoizeObjArg, memoizeArraylike, memoizeHashlike, MemoizeHashFunc, MemoiseArrayFunc } from './util/memoize'

export {
intersectRects,
Expand Down
2 changes: 1 addition & 1 deletion packages/common/src/scrollgrid/SimpleScrollGrid.tsx
Expand Up @@ -193,7 +193,7 @@ export class SimpleScrollGrid extends BaseComponent<SimpleScrollGridProps, Simpl

// TODO: can do a really simple print-view. dont need to join rows
handleSizing = () => {
this.setState({
this.safeSetState({
shrinkWidth: this.computeShrinkWidth(), // will create each chunk's <colgroup>. TODO: precompute hasShrinkWidth
...this.computeScrollerDims(),
})
Expand Down
12 changes: 9 additions & 3 deletions packages/common/src/util/memoize.ts
Expand Up @@ -60,11 +60,14 @@ export function memoizeObjArg<Arg extends Dictionary, Res>(
}
}

export type MemoiseArrayFunc<Args extends any[], Res> =
(argSets: Args[]) => Res[]

export function memoizeArraylike<Args extends any[], Res>( // used at all?
workerFunc: (...args: Args) => Res,
resEquality?: (res0: Res, res1: Res) => boolean,
teardownFunc?: (res: Res) => void,
): (argSets: Args[]) => Res[] {
): MemoiseArrayFunc<Args, Res> {
let currentArgSets: Args[] = []
let currentResults: Res[] = []

Expand Down Expand Up @@ -102,11 +105,14 @@ export function memoizeArraylike<Args extends any[], Res>( // used at all?
}
}

export function memoizeHashlike<Args extends any[], Res>( // used?
export type MemoizeHashFunc<Args extends any[], Res> =
(argHash: { [key: string]: Args }) => { [key: string]: Res }

export function memoizeHashlike<Args extends any[], Res>(
workerFunc: (...args: Args) => Res,
resEquality?: (res0: Res, res1: Res) => boolean,
teardownFunc?: (res: Res) => void, // TODO: change arg order
): (argHash: { [key: string]: Args }) => { [key: string]: Res } {
): MemoizeHashFunc<Args, Res> {
let currentArgHash: { [key: string]: Args } = {}
let currentResHash: { [key: string]: Res } = {}

Expand Down
7 changes: 7 additions & 0 deletions packages/common/src/vdom-util.tsx
Expand Up @@ -26,6 +26,13 @@ export abstract class PureComponent<Props=Dictionary, State=Dictionary> extends
return !compareObjs(this.props, nextProps, this.propEquality) ||
!compareObjs(this.state, nextState, this.stateEquality)
}

// HACK for freakin' React StrictMode
safeSetState(newState: Partial<State>): void {
if (!compareObjs(this.state, { ...this.state, ...newState }, this.stateEquality)) {
this.setState(newState)
}
}
}

PureComponent.prototype.propEquality = {}
Expand Down
2 changes: 1 addition & 1 deletion packages/daygrid/src/TableRow.tsx
Expand Up @@ -332,7 +332,7 @@ export class TableRow extends DateComponent<TableRowProps, TableRowState> {
const newInstanceHeights = this.queryEventInstanceHeights()
const limitByContentHeight = props.dayMaxEvents === true || props.dayMaxEventRows === true

this.setState({
this.safeSetState({
// HACK to prevent oscillations of events being shown/hidden from max-event-rows
// Essentially, once you compute an element's height, never null-out.
// TODO: always display all events, as visibility:hidden?
Expand Down

0 comments on commit 7f8c109

Please sign in to comment.