How to interact with a HTML element in React?
Use useRef
- Embed HTML content
import { useRef, useEffect } from 'react'
const TestComponent = () => {
const rootDiv = useRef(null)
useEffect(() => {
const root = rootDiv.current
root.innerHTML = `<span>Hello</span>`
}, [])
return <div ref={rootDiv}></div>
}
export default TestComponent
import { useRef, useEffect } from 'react'
const TestComponent = () => {
const rootDiv = useRef(null)
useEffect(() => {
const root = rootDiv.current
root.innerHTML = `<span>Hello</span>`
}, [])
return <div ref={rootDiv}></div>
}
export default TestComponent
import { useRef, useEffect } from 'react' const TestComponent = () => { const rootDiv = useRef(null) useEffect(() => { const root = rootDiv.current root.innerHTML = `<span>Hello</span>` }, []) return <div ref={rootDiv}></div> } export default TestComponent
- Focus an editable div element
import { useEffect, useRef, useState } from 'react'
const Note = () => {
const [isEditable, setEditable] = useState(false)
const contentDiv = useRef(null)
useEffect(() => { // After UI is updated
if (isEditable) {
const refContentDiv = contentDiv.current
refContentDiv.focus()
}
}, [isEditable])
function onEditNote() {
setEditable(true) // Schedule for UI update
}
function onSaveNote() {
setEditable(false) // Schedule for UI update
}
return (
<>
{isEditable ? (
<div onClick={onSaveNote}>
Save Note
</div>
) : (
<div onClick={onEditNote}>
Edit Note
</div>
)}
<div
ref={contentDiv}
contentEditable={isEditable}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusm od
tempor incidi dunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation
</div>
</>
)
}
export default Note
import { useEffect, useRef, useState } from 'react'
const Note = () => {
const [isEditable, setEditable] = useState(false)
const contentDiv = useRef(null)
useEffect(() => { // After UI is updated
if (isEditable) {
const refContentDiv = contentDiv.current
refContentDiv.focus()
}
}, [isEditable])
function onEditNote() {
setEditable(true) // Schedule for UI update
}
function onSaveNote() {
setEditable(false) // Schedule for UI update
}
return (
<>
{isEditable ? (
<div onClick={onSaveNote}>
Save Note
</div>
) : (
<div onClick={onEditNote}>
Edit Note
</div>
)}
<div
ref={contentDiv}
contentEditable={isEditable}
>
Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusm od
tempor incidi dunt ut labore et dolore magna aliqua. Ut enim ad minim
veniam, quis nostrud exercitation
</div>
</>
)
}
export default Note
import { useEffect, useRef, useState } from 'react' const Note = () => { const [isEditable, setEditable] = useState(false) const contentDiv = useRef(null) useEffect(() => { // After UI is updated if (isEditable) { const refContentDiv = contentDiv.current refContentDiv.focus() } }, [isEditable]) function onEditNote() { setEditable(true) // Schedule for UI update } function onSaveNote() { setEditable(false) // Schedule for UI update } return ( <> {isEditable ? ( <div onClick={onSaveNote}> Save Note </div> ) : ( <div onClick={onEditNote}> Edit Note </div> )} <div ref={contentDiv} contentEditable={isEditable} > Lorem ipsum dolor sit amet, consectetur adipiscing elit, sed do eiusm od tempor incidi dunt ut labore et dolore magna aliqua. Ut enim ad minim veniam, quis nostrud exercitation </div> </> ) } export default Note
How to render a React component into a DOM element?
- HTML file
<!DOCTYPE html>
<html lang="en">
<body>
<div id="id-component-test"></div>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<body>
<div id="id-component-test"></div>
</body>
</html>
<!DOCTYPE html> <html lang="en"> <body> <div id="id-component-test"></div> </body> </html>
- React component
import ReactDOM from 'react-dom'
const TestComponent = () => {
...
}
ReactDOM.render(<TestComponent />, document.getElementById('id-component-test'))
import ReactDOM from 'react-dom'
const TestComponent = () => {
...
}
ReactDOM.render(<TestComponent />, document.getElementById('id-component-test'))
import ReactDOM from 'react-dom' const TestComponent = () => { ... } ReactDOM.render(<TestComponent />, document.getElementById('id-component-test'))
How to style a component having content of an external HTML file (url)?
- Get html source code
export const fetchHtmlUrl = async (htmlUrl: string) => { // htmlUrl = https://xxx.xx/abc.html
const { data } = await axios.get(htmlUrl)
return data
}
export const fetchHtmlUrl = async (htmlUrl: string) => { // htmlUrl = https://xxx.xx/abc.html
const { data } = await axios.get(htmlUrl)
return data
}
export const fetchHtmlUrl = async (htmlUrl: string) => { // htmlUrl = https://xxx.xx/abc.html const { data } = await axios.get(htmlUrl) return data }
import { useRef, useEffect } from 'react'
import { fetchHtmlUrl } from 'src/network/restful/restApi'
import { useQuery } from 'react-query'
import './index.scss'
const TestComponent = ({ htmlUrl }) => {
const { data, isLoading } = useQuery(['fetchHtmlUrl', htmlUrl], () =>
fetchHtmlUrl(htmlUrl)
)
const rootDiv = useRef(null)
useEffect(() => {
if (!data) {
return
}
const root = rootDiv.current
root.innerHTML = data.trim()
}, [data])
if (isLoading) {
return null
}
return <div ref={rootDiv} className='test-component'></div>
}
export default TestComponent
import { useRef, useEffect } from 'react'
import { fetchHtmlUrl } from 'src/network/restful/restApi'
import { useQuery } from 'react-query'
import './index.scss'
const TestComponent = ({ htmlUrl }) => {
const { data, isLoading } = useQuery(['fetchHtmlUrl', htmlUrl], () =>
fetchHtmlUrl(htmlUrl)
)
const rootDiv = useRef(null)
useEffect(() => {
if (!data) {
return
}
const root = rootDiv.current
root.innerHTML = data.trim()
}, [data])
if (isLoading) {
return null
}
return <div ref={rootDiv} className='test-component'></div>
}
export default TestComponent
import { useRef, useEffect } from 'react' import { fetchHtmlUrl } from 'src/network/restful/restApi' import { useQuery } from 'react-query' import './index.scss' const TestComponent = ({ htmlUrl }) => { const { data, isLoading } = useQuery(['fetchHtmlUrl', htmlUrl], () => fetchHtmlUrl(htmlUrl) ) const rootDiv = useRef(null) useEffect(() => { if (!data) { return } const root = rootDiv.current root.innerHTML = data.trim() }, [data]) if (isLoading) { return null } return <div ref={rootDiv} className='test-component'></div> } export default TestComponent
- Create css file to style the page
// index.scss
.test-component {
line-height: 1.4em;
color: #666;
-webkit-font-smoothing: antialiased;
h1, h2, h3, h4, h5, h6 {
line-height: 1.4em;
color: #666;
}
h1 {
font-weight: 300;
}
...
}
// index.scss
.test-component {
line-height: 1.4em;
color: #666;
-webkit-font-smoothing: antialiased;
h1, h2, h3, h4, h5, h6 {
line-height: 1.4em;
color: #666;
}
h1 {
font-weight: 300;
}
...
}
// index.scss .test-component { line-height: 1.4em; color: #666; -webkit-font-smoothing: antialiased; h1, h2, h3, h4, h5, h6 { line-height: 1.4em; color: #666; } h1 { font-weight: 300; } ... }
How to render custom iframe in React?
const TestComponent = ({ }) => {
////////////////////////////
// Define iframe reference
const iframeRef = useRef(null);
useEffect(() => {
const iframe = iframeRef.current;
let timer;
if (!iframe) {
return;
}
timer = setTimeout(() => {
const win = iframe.contentWindow;
////////////////////////////////////
// Communicate with iframe content
win.addEventListener('message', (event) => {
switch (event.data?.type) {
case 'exitFullscreen':
// do something;
break;
default:
}
});
//////////////////
// Inject style
const doc = win.document;
const { body } = doc;
const style = doc.createElement('style');
style.innerHTML = `
html, body { width: 100%; height: 100%; }
body { margin: 0; background: #000000; overflow: hidden; }
...
@media only screen and (max-width: 629px) {
.video-js:not(.vjs-has-started) .vjs-tech {
opacity: 0.4!important;
}
}`;
body.appendChild(style);
//////////////////////////
// inject a HTML element
const video = doc.createElement('video');
video.className = 'video-js vjs-fluid';
video.setAttribute('one-attribute', 'some-value');
body.appendChild(video);
//////////////////////////
// inject script element
const bcScript = doc.createElement('script');
bcScript.src = `https://xxxxx.xx/abcd.js`;
bcScript.onload = () => {
// do something ...
};
body.appendChild(bcScript);
}, 100);
return () => {
iframeRef.current = null;
if (timer) {
clearTimeout(timer);
}
};
}, []);
return (
<iframe allowFullScreen={false} ref={iframeRef} />
);
};
export default TestComponent;
const TestComponent = ({ }) => {
////////////////////////////
// Define iframe reference
const iframeRef = useRef(null);
useEffect(() => {
const iframe = iframeRef.current;
let timer;
if (!iframe) {
return;
}
timer = setTimeout(() => {
const win = iframe.contentWindow;
////////////////////////////////////
// Communicate with iframe content
win.addEventListener('message', (event) => {
switch (event.data?.type) {
case 'exitFullscreen':
// do something;
break;
default:
}
});
//////////////////
// Inject style
const doc = win.document;
const { body } = doc;
const style = doc.createElement('style');
style.innerHTML = `
html, body { width: 100%; height: 100%; }
body { margin: 0; background: #000000; overflow: hidden; }
...
@media only screen and (max-width: 629px) {
.video-js:not(.vjs-has-started) .vjs-tech {
opacity: 0.4!important;
}
}`;
body.appendChild(style);
//////////////////////////
// inject a HTML element
const video = doc.createElement('video');
video.className = 'video-js vjs-fluid';
video.setAttribute('one-attribute', 'some-value');
body.appendChild(video);
//////////////////////////
// inject script element
const bcScript = doc.createElement('script');
bcScript.src = `https://xxxxx.xx/abcd.js`;
bcScript.onload = () => {
// do something ...
};
body.appendChild(bcScript);
}, 100);
return () => {
iframeRef.current = null;
if (timer) {
clearTimeout(timer);
}
};
}, []);
return (
<iframe allowFullScreen={false} ref={iframeRef} />
);
};
export default TestComponent;
const TestComponent = ({ }) => { //////////////////////////// // Define iframe reference const iframeRef = useRef(null); useEffect(() => { const iframe = iframeRef.current; let timer; if (!iframe) { return; } timer = setTimeout(() => { const win = iframe.contentWindow; //////////////////////////////////// // Communicate with iframe content win.addEventListener('message', (event) => { switch (event.data?.type) { case 'exitFullscreen': // do something; break; default: } }); ////////////////// // Inject style const doc = win.document; const { body } = doc; const style = doc.createElement('style'); style.innerHTML = ` html, body { width: 100%; height: 100%; } body { margin: 0; background: #000000; overflow: hidden; } ... @media only screen and (max-width: 629px) { .video-js:not(.vjs-has-started) .vjs-tech { opacity: 0.4!important; } }`; body.appendChild(style); ////////////////////////// // inject a HTML element const video = doc.createElement('video'); video.className = 'video-js vjs-fluid'; video.setAttribute('one-attribute', 'some-value'); body.appendChild(video); ////////////////////////// // inject script element const bcScript = doc.createElement('script'); bcScript.src = `https://xxxxx.xx/abcd.js`; bcScript.onload = () => { // do something ... }; body.appendChild(bcScript); }, 100); return () => { iframeRef.current = null; if (timer) { clearTimeout(timer); } }; }, []); return ( <iframe allowFullScreen={false} ref={iframeRef} /> ); }; export default TestComponent;
Useful DOM APIs
- Select all elements having a class name
- [id^=’someId’]: match all ids starting with someId
- [id$=’someId’]: match all ids ending with someId
- [id*=’someId’]: match all ids containing someId
const elements = document.querySelectorAll(
'div[class*="contain-a-class"]'
)
const elements = document.querySelectorAll(
'div[class*="contain-a-class"]'
)
const elements = document.querySelectorAll( 'div[class*="contain-a-class"]' )
Leave a Reply