2

I'm encountering an error when attempting to initialize Keycloak in my React application. The error message states:

Failed to initialize adapter: Error: A 'Keycloak' instance can only be initialized once. 

This occurs specifically when I wrap my application with <React.StrictMode>.

Here's how I've structured my code:

I have a separate file for Keycloak configuration (keycloakConfig.js) where I define my Keycloak instance:

import Keycloak from 'keycloak-js'; const keycloakConfig = { url: 'http://192.168.12.231:8080/auth/', realm: 'MyRelm', clientId: 'client', }; const keycloak = new Keycloak(keycloakConfig); export default keycloak; 

And in my component (Management.js), I'm using this Keycloak instance to authenticate users:

import React, { useState, useEffect } from "react"; import { NavLink, Outlet } from "react-router-dom"; import keycloak from "../keycloakConfig"; import { jwtDecode } from "jwt-decode"; function Management() { // State and effect hooks to handle authentication and user information // ... useEffect(() => { // Keycloak initialization code // ... }, []); // Functions to handle login and logout // ... // Render function // ... return ( // JSX structure for the component // ... ); } export default Management; 

I'm unsure why this error is occurring, especially in conjunction with <React.StrictMode>. How can I resolve this issue and ensure that Keycloak initializes correctly in my React application, even within <React.StrictMode>? Any insights or alternative approaches would be greatly appreciated. Thank you!

0

3 Answers 3

3

I think I found the answer to my question in the following post. https://stackoverflow.com/a/72585970/9897918

React 18 now has Strict.Mode which can mount, unmount, and remount components which causes the abortController to issue an error on the first unmount. Remember, this only happens in development mode when Strict.Mode is applied in your index.js. We can check for that behaviour while in development-mode. https://reactjs.org/docs/strict-mode.html#ensuring-reusable-state

Sign up to request clarification or add additional context in comments.

Comments

2

In Strict.Mode, the problem was solved in the following way

I created a useRef variable and set its value to false

const didInit = useRef(false); 

I checked the defined variable before initialization Keycloak

 if (!didInit.current) 

If the value of the variable is false, I True it and do init

didInit.current = true; 

The above code was edited as follows

 const didInit = useRef(false); useEffect(() => { const initKeycloak = async () => { try { if (!didInit.current) { didInit.current = true; const auth = await keycloak.init({ onLoad: 'check-sso', initOptions: { pkceMethod: 'S256', checkLoginIframe: false } }); console.log(`User is ${auth ? 'authenticated' : 'not authenticated'}`); setAuthenticated(auth); if (auth) { const token = keycloak.token; const decodedToken = jwtDecode(token); const roles = decodedToken.realm_access.roles; const name = decodedToken.name setUserRoles(roles); setFullName(name); } } } catch (error) { console.error('Failed to initialize adapter:', error); } }; 

Comments

0

In keycloak v 25.0.0 and above you can find flag didInitialize on Keycloak class (NOTE: it is not in types hoverwer still you can find it after logging kc instance to the console).

Try to use it in your code

useEffect(() => { if (keycloak.didInitialize) { return } // Keycloak initialization code // ... }, []); 

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.