I have a portal component that is outside react component tree and I'm using createPortal method from react dom to insert a Dom element inside the body element. The insertion is not working as expected.
Stackblitz link
main.tsx
import { StrictMode } from 'react'
import { createRoot } from 'react-dom/client'
import './index.css'
import App from './App.tsx'
createRoot(document.getElementById('root')!).render(
<StrictMode>
<App />
</StrictMode>,
)
App.tsx
import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
function App() {
const [count, setCount] = useState(0);
return (
<>
<div>
<a href="https://vite.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
</>
);
}
export default App;
dupe.tsx
// Trying to insert H1 tag with createPortal method
import { createPortal } from 'react-dom';
import './App.css';
export function Portal() {
return (
<>
<h1>Hello!</h1>
{createPortal(
<h1>Heading</h1>,
document.getElementById('modal') as HTMLElement
)}
</>
);
}
export default Portal;
// The div modal id here
<body>
<div id="root"></div>
<script type="module" src="/src/main.tsx"></script>
<div id="modal"></div>
</body>
Where am I Wrong?
You have to also render the component that creates and renders the React portal.
Example: In your sandbox import Portal
and render it in App
.
App.tsx
import { useState } from 'react';
import reactLogo from './assets/react.svg';
import viteLogo from '/vite.svg';
import './App.css';
import Portal from './dupe'; // <-- import Portal component
function App() {
const [count, setCount] = useState(0);
return (
<>
<div>
<a href="https://vite.dev" target="_blank">
<img src={viteLogo} className="logo" alt="Vite logo" />
</a>
<a href="https://react.dev" target="_blank">
<img src={reactLogo} className="logo react" alt="React logo" />
</a>
</div>
<h1>Vite + React</h1>
<div className="card">
<button onClick={() => setCount((count) => count + 1)}>
count is {count}
</button>
<p>
Edit <code>src/App.tsx</code> and save to test HMR
</p>
</div>
<p className="read-the-docs">
Click on the Vite and React logos to learn more
</p>
<Portal /> {/* <-- Render Portal Component */}
</>
);
}
export default App;