I have a react application that uses Auth0 for authentication. Bare bones it works OK but as soon as I started using some of the react-bootstrap and react-routing-bootstrap components to make the nav bar look a little better I started getting an error that is pointing to a line in the boilerplate Auth0 code I was asked to setup when iniitalizing. I get ‘React children only expected to receive a single React element child’.
Any ideas on what I can do to diagnose the problem?
Thank you.
Kevin
Hey there @rkevinburton!
Can you tell us more about the stack you’re using? Any docs/ quickstarts / SDKs of ours that you use? Any links appreciated!
This is a react app. I basically followed the steps outlined in https://manage.auth0.com/dashboard/us/burton/applications/AS9i1ojNXqSwFGCREZ7t0Ob5oW1PlBcm/quickstart.
-
Install dependencies
-
Create react-router’s history
instance
-
Install the Auth0 React wrapper (this is where the error points to)
-
Restoring Login State with Social Providers
-
Create the NavBar component ( I renamed it to LoginLogout)
-
Integrate the SDK (I am using TypeScript and Redux so index.js => index.tsx and App.js => App.tsx. In Index.tsx I have to insert the ‘Provider’ component defined in react-redux like:
ReactDOM.render(
<React.StrictMode>
<Auth0Provider
domain={config.domain}
client_id={config.clientId}
redirect_uri={window.location.origin}
onRedirectCallback={onRedirectCallback}
>
<Provider store={store}>
<App />
</Provider>
</Auth0Provider>
</React.StrictMode>,
document.getElementById('root')
);
And App.tsx looks like (truncated for breivity)
. . . .
function App() {
const { loading } = useAuth0();
if (loading) {
return <div>Loading...</div>;
}
return (
<div className="App">
<Router history={history}>
<div>
<Switch>
<Route path="/" exact component={BSoftList} />
<Route path="/bsoft/new" exact component={BSoftCreate} />
<Route path="/bsoft/edit/:id" exact component={BSoftEdit} />
<Route path="/bsoft/delete/:id" exact component={BSoftDelete} />
<Route path="/bsoft/:id" exact component={BSoftShow} />
</Switch>
<Header />
</div>
</Router>
<header className="App-header">
. . .
With Header.tsx (notice the heavy sprinkling of react-bootstrap and react-routing-bootstrap) that has LoginLogout.tsx nested like:
. . . .
const Header = () => {
return (
<Navbar className="bg-light justify-content-between">
<Navbar.Brand href="#home">React-Bootstrap</Navbar.Brand>
<Form inline>
<InputGroup>
<InputGroup.Prepend>
<InputGroup.Text id="basic-addon1">@</InputGroup.Text>
</InputGroup.Prepend>
<FormControl
placeholder="Username"
aria-label="Username"
aria-describedby="basic-addon1"
/>
</InputGroup>
</Form>
<Form inline>
<FormControl type="text" placeholder="Search" className=" mr-sm-2" />
<Button type="submit">Submit</Button>
</Form>
**<LoginLogout/>**
<LinkContainer to="/">
. . .
Finally LoginLogout component:
import React from "react";
import { useAuth0 } from "../react-auth0-spa";
const LoginLogout = () => {
const { isAuthenticated, loginWithRedirect, logout } = useAuth0();
return (
<div>
{!isAuthenticated && (
<button onClick={() => loginWithRedirect({})}>Log in</button>
)}
{isAuthenticated && <button onClick={() => logout()}>Log out</button>}
</div>
);
};
export default LoginLogout;
Thank you for looking at this.
Kevin
Did you figure out how to implement this correclty?