Reputation: 2738
I would like to know how to load the HTML form in the iframe in reactjs.
I have one form component that has all the input fields, and I want to load that form component in the iframe. I would like to know how I can do that.
const Form = () => {
return (
<>
<iframe name="iframe-form" title="This is an iframe form." />
<form target="iframe-form" onSubmit={handleSubmit}>
<div>
<label htmlFor="name">Name</label>
<input
type="text"
id="name"
/>
</div>
<div>
<label htmlFor="email">Email</label>
<input type="email" id="email" />
</div>
<button>Submit</button>
</form>
</>
);
};
export default Form;
Currently, it's rendering like this.
Upvotes: 2
Views: 873
Reputation: 20830
Use ReactDOMServer.renderToString
with iframe
's srcDoc
attribute.
import ReactDOMServer from "react-dom/server";
export default function App() {
return (
<div className="App">
<iframe
name="iframe-form"
title="This is an iframe form."
srcDoc={ReactDOMServer.renderToString(<Form />)}
/>
</div>
);
}
const Form = () => {
return (
<form target="iframe-form">
<div>
<label htmlFor="name">Name</label>
<input type="text" id="name" />
</div>
<div>
<label htmlFor="email">Email</label>
<input type="email" id="email" />
</div>
<button>Submit</button>
</form>
);
};
Upvotes: 1
Reputation: 660
According to the React documentation, 'React Portals' allow us to render children into a DOM node that exists outside of the parent component’s DOM hierarchy. Basically, portals let us render children wherever we want to.
So the large explanation would be create a portal:
ReactDOM.createPortal(child, container)
In this case, the child is a React element, fragment, or string, and the container is the
DOM
location or node to which the portal should be rendered.With a React portal, we can choose where to place a DOM node in the DOM hierarchy, the portal’s contents are also considered children of the parent’s virtual DOM.
MyComponent.js
import React from 'react'
function MyComponent() {
return (
<div>
<p style={{color: 'red'}}>Testing to see if my component renders!</p>
</div>
)
}
export default MyComponent;
Now, let’s create a file called CustomIframe.js and write the following code:
import React, { useState } from 'react'
import { createPortal } from 'react-dom'
const CustomIframe = ({
children,
...props
}) => {
const [contentRef, setContentRef] = useState(null)
const mountNode =
contentRef?.contentWindow?.document?.body
return (
<iframe {...props} ref={setContentRef}>
{mountNode && createPortal(children, mountNode)}
</iframe>
)
}
export default CustomIframe;
We created a ref with the
useState()
Hook, therefore, once the state is updated, the component will re-render.We also got access to the iframe document body, then created a portal to render the children passed to iframe in this body instead:
import './App.css';
import CustomIframe from './CustomIframe';
import MyComponent from './MyComponent';
function App() {
return (
<CustomIframe title='A custom made iframe'>
<MyComponent />
</CustomIframe>
);
}
export default App;
You can pass any React app or component as a child of CustomIframe
, and it should work fine.
The React app or component will become encapsulated, meaning you can develop and maintain it independently.
You can also achieve the same encapsulation as above using a library called react frame component. To install it, run the following command:
npm install --save react-frame-component
Encapsulate your component as follows:
import Frame from 'react-frame-component';
function App() {
return (
<div className='App'>
<p>Iframes in React</p>
<Frame >
<MyComponent />
</Frame>
</div>
);
}
export default App;
Upvotes: 2