Skip to content

Commit 834c755

Browse files
wallzeroschlesiger
andauthored
Starting the router is a side effect and must be wrapped in useEffect for React.StrictMode and React.ConcurrentMode (#607)
Co-authored-by: schlesiger <51380403+schlesiger@users.noreply.github.com>
1 parent 4c8188f commit 834c755

File tree

1 file changed

+26
-20
lines changed

1 file changed

+26
-20
lines changed

src/components/UIRouter.tsx

Lines changed: 26 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
/** @packageDocumentation @reactapi @module components */
22
import * as React from 'react';
3-
import { useRef } from 'react';
3+
import { useEffect, useRef, useState } from 'react';
44

55
import { UIRouter as _UIRouter, UIRouterPlugin, servicesPlugin, PluginFactory } from '@uirouter/core';
66

@@ -20,7 +20,7 @@ import { ReactStateDeclaration } from '../interface';
2020
* ```
2121
*/
2222
export const UIRouterContext = React.createContext<_UIRouter>(undefined);
23-
/** @deprecated use [[useRouter]] or React.useContext(UIRouterContext) */
23+
/** @deprecated use [[useRouter]] or React.useContext(UIRouterContext) */
2424
export const UIRouterConsumer = UIRouterContext.Consumer;
2525

2626
export interface UIRouterProps {
@@ -124,25 +124,31 @@ export const InstanceOrPluginsMissingError = `Router instance or plugins missing
124124
*/
125125
export function UIRouter(props: UIRouterProps) {
126126
const uiRouter = useRef<UIRouterReact>();
127+
const [_hasStarted, start] = useState<boolean>(false);
127128

128-
// Router hasn't been initialised yet, this is the first render
129-
if (!uiRouter.current) {
130-
const { config, states, plugins, router } = props;
131-
if (router) {
132-
uiRouter.current = router;
133-
} else if (plugins) {
134-
// We need to create a new instance of the Router and register plugins, config and states
135-
uiRouter.current = new UIRouterReact();
136-
uiRouter.current.plugin(servicesPlugin); // services plugins is necessary for the router to fuction
137-
plugins.forEach(plugin => uiRouter.current.plugin(plugin));
138-
if (config) config(uiRouter.current);
139-
(states || []).forEach(state => uiRouter.current.stateRegistry.register(state));
140-
} else {
141-
throw new Error(InstanceOrPluginsMissingError);
142-
}
129+
useEffect(() => {
130+
// Router hasn't been initialised yet, this is the first render
131+
if (!uiRouter.current) {
132+
const { config, states, plugins, router } = props;
133+
if (router) {
134+
uiRouter.current = router;
135+
} else if (plugins) {
136+
// We need to create a new instance of the Router and register plugins, config and states
137+
uiRouter.current = new UIRouterReact();
138+
uiRouter.current.plugin(servicesPlugin); // services plugins is necessary for the router to fuction
139+
plugins.forEach(plugin => uiRouter.current.plugin(plugin));
140+
if (config) config(uiRouter.current);
141+
(states || []).forEach(state => uiRouter.current.stateRegistry.register(state));
142+
} else {
143+
throw new Error(InstanceOrPluginsMissingError);
144+
}
143145

144-
uiRouter.current.start();
145-
}
146+
uiRouter.current.start();
147+
start(true);
148+
}
149+
});
146150

147-
return <UIRouterContext.Provider value={uiRouter.current}>{props.children}</UIRouterContext.Provider>;
151+
return uiRouter.current ? (
152+
<UIRouterContext.Provider value={uiRouter.current}>{props.children}</UIRouterContext.Provider>
153+
) : null;
148154
}

0 commit comments

Comments
 (0)