okta-react
okta-react copied to clipboard
Okta React v5 + TypeScript import issue
I'm trying to upgrade OktaDev Schematics to use Okta React v5. Here's the code I'm trying to make work:
import React, { Component } from 'react';
import { withOktaAuth } from '@okta/okta-react';
import './App.css';
import logo from './logo.svg';
import {OktaAuth} from "@okta/okta-auth-js";
interface HomeProps {
oktaAuth: OktaAuth;
authState: any;
}
interface HomeState {
}
export default withOktaAuth(class Home extends Component<HomeProps, HomeState> {
constructor(props: HomeProps) {
super(props);
this.login = this.login.bind(this);
this.logout = this.logout.bind(this);
}
async login() {
await this.props.oktaAuth.signInWithRedirect();
}
async logout() {
await this.props.oktaAuth.signOut();
}
...
}
It throws the following error when I try to run it:
TypeScript error in /Users/mraible/dev/okta/schematics/apps/react-app-ts/src/Home.tsx(15,35):
Argument of type 'typeof Home' is not assignable to parameter of type 'ComponentType<IOktaContext>'.
Type 'typeof Home' is not assignable to type 'ComponentClass<IOktaContext, any>'.
Construct signature return types 'Home' and 'Component<IOktaContext, any, any>' are incompatible.
The types of 'props' are incompatible between these types.
Type 'Readonly<HomeProps> & Readonly<{ children?: ReactNode; }>' is not assignable to type 'Readonly<IOktaContext> & Readonly<{ children?: ReactNode; }>'.
Property '_onAuthRequired' is missing in type 'Readonly<HomeProps> & Readonly<{ children?: ReactNode; }>' but required in type 'Readonly<IOktaContext>'. TS2345
13 | }
14 |
> 15 | export default withOktaAuth(class Home extends Component<HomeProps, HomeState> {
| ^
16 | constructor(props: HomeProps) {
17 | super(props);
18 | this.login = this.login.bind(this);
I was able to fix it by changing HomeProps
to extend IOktaContext
:
import {IOktaContext} from "@okta/okta-react/bundles/types/OktaContext";
interface HomeProps extends IOktaContext {
oktaAuth: OktaAuth;
authState: any;
}
Since the import looks kinda funny, I tried using OktaContext
instead:
import { OktaContext, withOktaAuth } from '@okta/okta-react';
This results in:
'OktaContext' refers to a value, but is being used as a type here. Did you mean 'typeof OktaContext'? TS2749
5 | import {OktaAuth} from "@okta/okta-auth-js";
6 |
> 7 | interface HomeProps extends OktaContext {
| ^
8 | oktaAuth: OktaAuth;
9 | authState: any;
10 | }
Adding onAuthRequired
also works, but the import is similarly funny looking.
import {OnAuthRequiredFunction} from "@okta/okta-react/bundles/types/OktaContext";
interface HomeProps {
oktaAuth: OktaAuth;
authState: AuthState;
_onAuthRequired: OnAuthRequiredFunction;
}
This seems to work with no funky imports.
interface HomeProps {
oktaAuth: OktaAuth;
authState: AuthState;
_onAuthRequired: any;
}
Hopefully this issue inspires some component-based TypeScript examples in the README. :)
can you not do:
import {OnAuthRequiredFunction} from "@okta/okta-react";
?
No. This code:
import React, { Component } from 'react';
import { AuthState, OktaAuth } from '@okta/okta-auth-js';
import { withOktaAuth, OnAuthRequiredFunction } from '@okta/okta-react';
import './App.css';
import logo from './logo.svg';
interface HomeProps {
oktaAuth: OktaAuth;
authState: AuthState;
_onAuthRequired: OnAuthRequiredFunction;
}
Results in:
Module '"@okta/okta-react"' has no exported member 'OnAuthRequiredFunction'. TS2305
I have another TypeScript issue when trying to upgrade my App.tsx
:
Argument of type 'typeof App' is not assignable to parameter of type 'ComponentType<RouteComponentProps<any, StaticContext, unknown>>'.
Type 'typeof App' is not assignable to type 'ComponentClass<RouteComponentProps<any, StaticContext, unknown>, any>'.
Construct signature return types 'App' and 'Component<RouteComponentProps<any, StaticContext, unknown>, any, any>' are incompatible.
The types of 'props' are incompatible between these types.
Type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>' is not assignable to type 'Readonly<RouteComponentProps<any, StaticContext, unknown>> & Readonly<{ children?: ReactNode; }>'.
Type 'Readonly<{}> & Readonly<{ children?: ReactNode; }>' is missing the following properties from type 'Readonly<RouteComponentProps<any, StaticContext, unknown>>': history, location, match TS2345
32 | }
33 |
> 34 | const AppWithRouterAccess = withRouter(App);
| ^
35 |
36 | class RouterApp extends Component {
37 | render() {
Here's my code:
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, withRouter } from 'react-router-dom';
import { OktaAuth, OktaAuthOptions, toRelativeUrl } from '@okta/okta-auth-js';
import { LoginCallback, Security } from '@okta/okta-react';
import Home from './Home';
const config: OktaAuthOptions = {
issuer: 'https://dev-foo.okta.com/oauth2/default',
clientId: 'bar',
redirectUri: window.location.origin + '/callback'
};
const oktaAuth = new OktaAuth(config);
class App extends Component {
restoreOriginalUri: any;
constructor(props: any) {
super(props);
this.restoreOriginalUri = async (_oktaAuth: OktaAuth, originalUri: string) => {
props.history.replace(toRelativeUrl(originalUri, window.location.origin));
};
}
render() {
return (
<Security oktaAuth={oktaAuth} restoreOriginalUri={this.restoreOriginalUri}>
<Route path="/" exact={true} component={Home}/>
<Route path="/callback" component={LoginCallback}/>
</Security>
);
}
}
const AppWithRouterAccess = withRouter(App);
class RouterApp extends Component {
render() {
return (<Router><AppWithRouterAccess/></Router>);
}
}
export default RouterApp;
If I add // @ts-ignore
, it works.
// @ts-ignore
const AppWithRouterAccess = withRouter(App);
FWIW, there's the PR to upgrade OktaDev Schematics.