Removes faulty error boundary from core, removes faulty ID provider from tldraw

This commit is contained in:
Steve Ruiz 2021-12-12 21:44:44 +00:00
parent ec7fbd2033
commit 5e6a4939d1
9 changed files with 41 additions and 230 deletions

View file

@ -11,10 +11,10 @@
"esbuild" "esbuild"
], ],
"scripts": { "scripts": {
"start:electron": "yarn dev",
"build:apps": "yarn build",
"dev": "electron-esbuild dev", "dev": "electron-esbuild dev",
"build": "electron-esbuild build", "start:electron": "yarn dev",
"build:apps": "yarn build:electron",
"build:electron": "electron-esbuild build",
"package": "electron-builder" "package": "electron-builder"
}, },
"devDependencies": { "devDependencies": {
@ -76,4 +76,4 @@
"publish": null "publish": null
}, },
"gitHead": "a7dac0f83ad998e205c2aab58182cb4ba4e099a6" "gitHead": "a7dac0f83ad998e205c2aab58182cb4ba4e099a6"
} }

View file

@ -10,8 +10,6 @@ import {
useKeyEvents, useKeyEvents,
} from '~hooks' } from '~hooks'
import type { TLBinding, TLBounds, TLPage, TLPageState, TLShape, TLSnapLine, TLUsers } from '~types' import type { TLBinding, TLBounds, TLPage, TLPageState, TLShape, TLSnapLine, TLUsers } from '~types'
import { ErrorFallback } from '~components/ErrorFallback'
import { ErrorBoundary } from '~components/ErrorBoundary'
import { Brush } from '~components/Brush' import { Brush } from '~components/Brush'
import { Page } from '~components/Page' import { Page } from '~components/Page'
import { Users } from '~components/Users' import { Users } from '~components/Users'
@ -93,28 +91,26 @@ export const Canvas = observer(function _Canvas<
return ( return (
<div id={id} className="tl-container" ref={rContainer}> <div id={id} className="tl-container" ref={rContainer}>
<div id="canvas" className="tl-absolute tl-canvas" ref={rCanvas} {...events}> <div id="canvas" className="tl-absolute tl-canvas" ref={rCanvas} {...events}>
<ErrorBoundary FallbackComponent={ErrorFallback} onReset={resetError}> {!hideGrid && grid && <Grid grid={grid} camera={pageState.camera} />}
{!hideGrid && grid && <Grid grid={grid} camera={pageState.camera} />} <div ref={rLayer} className="tl-absolute tl-layer" data-testid="layer">
<div ref={rLayer} className="tl-absolute tl-layer" data-testid="layer"> <Page
<Page page={page}
page={page} pageState={pageState}
pageState={pageState} hideBounds={hideBounds}
hideBounds={hideBounds} hideIndicators={hideIndicators}
hideIndicators={hideIndicators} hideHandles={hideHandles}
hideHandles={hideHandles} hideBindingHandles={hideBindingHandles}
hideBindingHandles={hideBindingHandles} hideCloneHandles={hideCloneHandles}
hideCloneHandles={hideCloneHandles} hideResizeHandles={hideResizeHandles}
hideResizeHandles={hideResizeHandles} hideRotateHandle={hideRotateHandle}
hideRotateHandle={hideRotateHandle} meta={meta}
meta={meta} />
/> {users && userId && (
{users && userId && ( <UsersIndicators userId={userId} users={users} page={page} meta={meta} />
<UsersIndicators userId={userId} users={users} page={page} meta={meta} /> )}
)} {pageState.brush && <Brush brush={pageState.brush} />}
{pageState.brush && <Brush brush={pageState.brush} />} {users && <Users userId={userId} users={users} />}
{users && <Users userId={userId} users={users} />} </div>
</div>
</ErrorBoundary>
<Overlay camera={pageState.camera}> <Overlay camera={pageState.camera}>
{snapLines && <SnapLines snapLines={snapLines} />} {snapLines && <SnapLines snapLines={snapLines} />}
</Overlay> </Overlay>

View file

@ -1,155 +0,0 @@
import * as React from 'react'
// Copied from https://github.com/bvaughn/react-error-boundary/blob/master/src/index.tsx
// (There's an issue with esm builds of this library, so we can't use it directly.)
const changedArray = (a: Array<unknown> = [], b: Array<unknown> = []) =>
a.length !== b.length || a.some((item, index) => !Object.is(item, b[index]))
interface FallbackProps {
error: Error
resetErrorBoundary: (...args: Array<unknown>) => void
}
interface ErrorBoundaryPropsWithComponent {
onResetKeysChange?: (
prevResetKeys: Array<unknown> | undefined,
resetKeys: Array<unknown> | undefined
) => void
onReset?: (...args: Array<unknown>) => void
onError?: (error: Error, info: { componentStack: string }) => void
resetKeys?: Array<unknown>
fallback?: never
FallbackComponent: React.ComponentType<FallbackProps>
fallbackRender?: never
}
declare function FallbackRender(
props: FallbackProps
): React.ReactElement<unknown, string | React.FunctionComponent | typeof React.Component> | null
interface ErrorBoundaryPropsWithRender {
onResetKeysChange?: (
prevResetKeys: Array<unknown> | undefined,
resetKeys: Array<unknown> | undefined
) => void
onReset?: (...args: Array<unknown>) => void
onError?: (error: Error, info: { componentStack: string }) => void
resetKeys?: Array<unknown>
fallback?: never
FallbackComponent?: never
fallbackRender: typeof FallbackRender
}
interface ErrorBoundaryPropsWithFallback {
onResetKeysChange?: (
prevResetKeys: Array<unknown> | undefined,
resetKeys: Array<unknown> | undefined
) => void
onReset?: (...args: Array<unknown>) => void
onError?: (error: Error, info: { componentStack: string }) => void
resetKeys?: Array<unknown>
fallback: React.ReactElement<
unknown,
string | React.FunctionComponent | typeof React.Component
> | null
FallbackComponent?: never
fallbackRender?: never
}
type ErrorBoundaryProps =
| ErrorBoundaryPropsWithFallback
| ErrorBoundaryPropsWithComponent
| ErrorBoundaryPropsWithRender
type ErrorBoundaryState = { error: Error | null }
const initialState: ErrorBoundaryState = { error: null }
class ErrorBoundary extends React.Component<
React.PropsWithRef<React.PropsWithChildren<ErrorBoundaryProps>>,
ErrorBoundaryState
> {
static getDerivedStateFromError(error: Error) {
return { error }
}
state = initialState
updatedWithError = false
resetErrorBoundary = (...args: Array<unknown>) => {
this.props.onReset?.(...args)
this.reset()
}
reset() {
this.updatedWithError = false
this.setState(initialState)
}
componentDidCatch(error: Error, info: React.ErrorInfo) {
this.props.onError?.(error, info)
}
componentDidMount() {
const { error } = this.state
if (error !== null) {
this.updatedWithError = true
}
}
componentDidUpdate(prevProps: ErrorBoundaryProps) {
const { error } = this.state
const { resetKeys } = this.props
// There's an edge case where if the thing that triggered the error
// happens to *also* be in the resetKeys array, we'd end up resetting
// the error boundary immediately. This would likely trigger a second
// error to be thrown.
// So we make sure that we don't check the resetKeys on the first call
// of cDU after the error is set
if (error !== null && !this.updatedWithError) {
this.updatedWithError = true
return
}
if (error !== null && changedArray(prevProps.resetKeys, resetKeys)) {
this.props.onResetKeysChange?.(prevProps.resetKeys, resetKeys)
this.reset()
}
}
render() {
const { error } = this.state
const { fallbackRender, FallbackComponent, fallback } = this.props
if (error !== null) {
const props = {
error,
resetErrorBoundary: this.resetErrorBoundary,
}
if (React.isValidElement(fallback)) {
return fallback
} else if (typeof fallbackRender === 'function') {
return fallbackRender(props)
} else if (FallbackComponent) {
return <FallbackComponent {...props} />
} else {
throw new Error(
'react-error-boundary requires either a fallback, fallbackRender, or FallbackComponent prop'
)
}
}
return this.props.children
}
}
export { ErrorBoundary }
export type {
FallbackProps,
ErrorBoundaryPropsWithComponent,
ErrorBoundaryPropsWithRender,
ErrorBoundaryPropsWithFallback,
ErrorBoundaryProps,
}

View file

@ -1 +0,0 @@
export * from './ErrorBoundary'

View file

@ -1,9 +0,0 @@
import * as React from 'react'
import { renderWithContext } from '~test'
import { ErrorFallback } from './ErrorFallback'
describe('error fallback', () => {
test('mounts component without crashing', () => {
renderWithContext(<ErrorFallback error={new Error()} resetErrorBoundary={() => void null} />)
})
})

View file

@ -1,20 +0,0 @@
import * as React from 'react'
import { useTLContext } from '~hooks'
interface ErrorFallbackProps {
error: Error
resetErrorBoundary: () => void
}
export const ErrorFallback = React.memo(function ErrorFallback({
error,
resetErrorBoundary,
}: ErrorFallbackProps) {
const { callbacks } = useTLContext()
React.useEffect(() => {
callbacks.onError?.(error)
}, [error, resetErrorBoundary, callbacks])
return null
})

View file

@ -1 +0,0 @@
export * from './ErrorFallback'

View file

@ -1,3 +1,7 @@
## 1.2.7
- Fixes crash due to a missing ID provider.
## 1.2.6 ## 1.2.6
- No minify on bundle. - No minify on bundle.

View file

@ -1,5 +1,4 @@
import * as React from 'react' import * as React from 'react'
import { IdProvider } from '@radix-ui/react-id'
import { Renderer } from '@tldraw/core' import { Renderer } from '@tldraw/core'
import { styled, dark } from '~styles' import { styled, dark } from '~styles'
import { TDDocument, TDShape, TDBinding, TDStatus, TDUser } from '~types' import { TDDocument, TDShape, TDBinding, TDStatus, TDUser } from '~types'
@ -301,21 +300,19 @@ export function Tldraw({
// Use the `key` to ensure that new selector hooks are made when the id changes // Use the `key` to ensure that new selector hooks are made when the id changes
return ( return (
<TldrawContext.Provider value={app}> <TldrawContext.Provider value={app}>
<IdProvider> <InnerTldraw
<InnerTldraw key={sId || 'Tldraw'}
key={sId || 'Tldraw'} id={sId}
id={sId} autofocus={autofocus}
autofocus={autofocus} showPages={showPages}
showPages={showPages} showMenu={showMenu}
showMenu={showMenu} showStyles={showStyles}
showStyles={showStyles} showZoom={showZoom}
showZoom={showZoom} showTools={showTools}
showTools={showTools} showUI={showUI}
showUI={showUI} showSponsorLink={showSponsorLink}
showSponsorLink={showSponsorLink} readOnly={readOnly}
readOnly={readOnly} />
/>
</IdProvider>
</TldrawContext.Provider> </TldrawContext.Provider>
) )
} }