简体   繁体   中英

React component renders twice

I have text from my Prismic CMS, where I want to apply 'dynamic words' on. Dynamic words are words from the CMS, that have an image linked to it, so if a text contains a dynamic word, it changes it to a span with data attributes, so an underline appears under each dynamic word, and if you click on it, the right image shows up.

In my code, I get the innerHTML of the text block, with the prismic render and all the tags inside of it, and then I want to change the innerHTML, to apply the dynamic words to the text and then change the innerHTML of the text block to the html with the dynamic words.

But I have a few issues, my React component renders twice, so when it renders the first time and I console log newText , it is the right one. But on the second render it also changes the data attributes of the dynamic word span's, so the whole html is getting screwed up.

Does anyone know why it would run twice, or maybe has a better solution to fix my problem?

 export const ArticleBodyText = ({ text, dynamic_words }) => { useEffect(() => { const textblocks = document.querySelectorAll('#textblock p'); textblocks.forEach(item => { const textblock = item.innerHTML; const newText = setDynamicWords(textblock, dynamic_words); console.log(newText); item.innerHTML = newText; }); }, [dynamic_words]); return ( <TextBlock id="textblock"> <RichText render={text} /> </TextBlock> ); };

search for a hook called useeffect once

https://www.robinwieruch.de/react-useeffect-only-once/

Just make a state that returns if true, so after the second render, nothing will happen.

 export const ArticleBodyText = ({ text, dynamic_words }) => { const [hasUpdated, setHasUpdated] = useState(false); useEffect(() => { if (hasUpdated) return; setHasUpdated(true); const textblocks = document.querySelectorAll('#textblock p'); textblocks.forEach(item => { const textblock = item.innerHTML; const newText = setDynamicWords(textblock, dynamic_words); console.log(newText); item.innerHTML = newText; }); }, [dynamic_words]); return ( <TextBlock id="textblock"> <RichText render={text} /> </TextBlock> ); };

Remove React.StrictMode from ReactDOM.render code

 ReactDOM.render( <React.StrictMode> <App /> </React.StrictMode>, document.getElementById('root') );
 ReactDOM.render( <> <App /> </>, document.getElementById('root') );

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM