From d690326f31774f4145a9500008015b175d0eea25 Mon Sep 17 00:00:00 2001 From: Connor Schlesiger Date: Thu, 13 Feb 2020 17:12:19 -0800 Subject: [PATCH] Starting the router is a side effect and must be wrapped in useEffect for React.StrictMode and React.ConcurrentMode --- src/components/UIRouter.tsx | 46 +++++++++++++++++++++---------------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/src/components/UIRouter.tsx b/src/components/UIRouter.tsx index a87abf03..71500df9 100644 --- a/src/components/UIRouter.tsx +++ b/src/components/UIRouter.tsx @@ -1,6 +1,6 @@ /** @packageDocumentation @reactapi @module components */ import * as React from 'react'; -import { useRef } from 'react'; +import { useEffect, useRef, useState } from 'react'; import { UIRouter as _UIRouter, UIRouterPlugin, servicesPlugin, PluginFactory } from '@uirouter/core'; @@ -20,7 +20,7 @@ import { ReactStateDeclaration } from '../interface'; * ``` */ export const UIRouterContext = React.createContext<_UIRouter>(undefined); - /** @deprecated use [[useRouter]] or React.useContext(UIRouterContext) */ +/** @deprecated use [[useRouter]] or React.useContext(UIRouterContext) */ export const UIRouterConsumer = UIRouterContext.Consumer; export interface UIRouterProps { @@ -124,25 +124,31 @@ export const InstanceOrPluginsMissingError = `Router instance or plugins missing */ export function UIRouter(props: UIRouterProps) { const uiRouter = useRef(); + const [_hasStarted, start] = useState(false); - // Router hasn't been initialised yet, this is the first render - if (!uiRouter.current) { - const { config, states, plugins, router } = props; - if (router) { - uiRouter.current = router; - } else if (plugins) { - // We need to create a new instance of the Router and register plugins, config and states - uiRouter.current = new UIRouterReact(); - uiRouter.current.plugin(servicesPlugin); // services plugins is necessary for the router to fuction - plugins.forEach(plugin => uiRouter.current.plugin(plugin)); - if (config) config(uiRouter.current); - (states || []).forEach(state => uiRouter.current.stateRegistry.register(state)); - } else { - throw new Error(InstanceOrPluginsMissingError); - } + useEffect(() => { + // Router hasn't been initialised yet, this is the first render + if (!uiRouter.current) { + const { config, states, plugins, router } = props; + if (router) { + uiRouter.current = router; + } else if (plugins) { + // We need to create a new instance of the Router and register plugins, config and states + uiRouter.current = new UIRouterReact(); + uiRouter.current.plugin(servicesPlugin); // services plugins is necessary for the router to fuction + plugins.forEach(plugin => uiRouter.current.plugin(plugin)); + if (config) config(uiRouter.current); + (states || []).forEach(state => uiRouter.current.stateRegistry.register(state)); + } else { + throw new Error(InstanceOrPluginsMissingError); + } - uiRouter.current.start(); - } + uiRouter.current.start(); + start(true); + } + }); - return {props.children}; + return uiRouter.current ? ( + {props.children} + ) : null; }