Skip to content

Commit

Permalink
Use getDerivedStateFromProps instead as class components don't suppor…
Browse files Browse the repository at this point in the history
…t setState in render
  • Loading branch information
timneutkens committed May 17, 2023
1 parent 6aa4349 commit af832a4
Show file tree
Hide file tree
Showing 2 changed files with 50 additions and 20 deletions.
26 changes: 25 additions & 1 deletion packages/next/src/client/components/error-boundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -41,9 +41,14 @@ interface ErrorBoundaryHandlerProps extends ErrorBoundaryProps {
pathname: string
}

interface ErrorBoundaryHandlerState {
error: Error | null
previousPathname: string
}

export class ErrorBoundaryHandler extends React.Component<
ErrorBoundaryHandlerProps,
{ error: Error | null; previousPathname: string }
ErrorBoundaryHandlerState
> {
constructor(props: ErrorBoundaryHandlerProps) {
super(props)
Expand All @@ -54,6 +59,25 @@ export class ErrorBoundaryHandler extends React.Component<
return { error }
}

static getDerivedStateFromProps(
props: ErrorBoundaryHandlerProps,
state: ErrorBoundaryHandlerState
): ErrorBoundaryHandlerState | null {
/**
* Handles reset of the error boundary when a navigation happens.
* Ensures the error boundary does not stay enabled when navigating to a new page.
* Approach of setState in render is safe as it checks the previous pathname and then overrides
* it as outlined in https://react.dev/reference/react/useState#storing-information-from-previous-renders
*/
if (props.pathname !== state.previousPathname && state.error) {
return {
error: null,
previousPathname: props.pathname,
}
}
return null
}

reset = () => {
this.setState({ error: null })
}
Expand Down
44 changes: 25 additions & 19 deletions packages/next/src/client/components/not-found-boundary.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -12,9 +12,14 @@ interface NotFoundErrorBoundaryProps extends NotFoundBoundaryProps {
pathname: string
}

interface NotFoundErrorBoundaryState {
notFoundTriggered: boolean
previousPathname: string
}

class NotFoundErrorBoundary extends React.Component<
NotFoundErrorBoundaryProps,
{ notFoundTriggered: boolean; previousPathname: string }
NotFoundErrorBoundaryState
> {
constructor(props: NotFoundErrorBoundaryProps) {
super(props)
Expand All @@ -32,26 +37,27 @@ class NotFoundErrorBoundary extends React.Component<
throw error
}

render() {
if (this.state.notFoundTriggered) {
/**
* Handles reset of the error boundary when a navigation happens.
* Ensures the error boundary does not stay enabled when navigating to a new page.
* Approach of setState in render is safe as it checks the previous pathname and then overrides
* it as outlined in https://react.dev/reference/react/useState#storing-information-from-previous-renders
*/
if (
this.props.pathname !== this.state.previousPathname &&
this.state.notFoundTriggered
) {
this.setState((_state) => {
return {
notFoundTriggered: false,
previousPathname: this.props.pathname,
}
})
static getDerivedStateFromProps(
props: NotFoundErrorBoundaryProps,
state: NotFoundErrorBoundaryState
): NotFoundErrorBoundaryState | null {
/**
* Handles reset of the error boundary when a navigation happens.
* Ensures the error boundary does not stay enabled when navigating to a new page.
* Approach of setState in render is safe as it checks the previous pathname and then overrides
* it as outlined in https://react.dev/reference/react/useState#storing-information-from-previous-renders
*/
if (props.pathname !== state.previousPathname && state.notFoundTriggered) {
return {
notFoundTriggered: false,
previousPathname: props.pathname,
}
}
return null
}

render() {
if (this.state.notFoundTriggered) {
return (
<>
<meta name="robots" content="noindex" />
Expand Down

0 comments on commit af832a4

Please sign in to comment.