20

My ReactJS component contains an iframe. In response to an event in the outer page, I need to reload the iframe. If the user has navigated to another page in the iframe, I need to reset it to the URL that it had when I first loaded the page. This URL is available in this.props.

I've tried using forceUpdate(). I can see that this causes the render method to run, but the iframe doesn't get reset - presumably because React can't tell that anything has changed.

At the moment I'm appending some random text to the iframe's querystring: this URL change forces React to re-render the iframe. However this feels a bit dirty: the page within the iframe is beyond my control so who knows what this extra querystring value might do?

resetIframe() {
    console.log("==== resetIframe ====");
    this.forceUpdate();
}

public render() {
    console.log("==== render ====");

    // How can I use just this.props.myUrl, without the Math.random()?
    let iframeUrl = this.props.myUrl + '&random=' + Math.random().toString();

    return <div>
        <button onClick={() => { this.resetIframe(); }}>Reset</button>
        <iframe src={iframeUrl}></iframe>
    </div>
}

(I'm using TypeScript too, if that makes a difference.)

teedyay
  • 23,293
  • 19
  • 66
  • 73

6 Answers6

34

I'd create a state variable with the random, and just update it on resetIframe:

state = {
     random: 0
}
resetIframe() {
    this.setState({random: this.state.random + 1});
}

public render() {
    return <div>
        <button onClick={() => { this.resetIframe(); }}>Reset</button>
        <iframe key={this.state.random} src={this.props.myUrl}></iframe>
    </div>
}

Here is a fiddle working: https://codesandbox.io/s/pp3n7wnzvx

Diogo Sgrillo
  • 2,601
  • 1
  • 18
  • 28
  • You're still appending things to the URL though - that's the part I want to avoid. What I really want is ` – teedyay Feb 16 '18 at 16:12
  • Take a look at my answer. I think if you combine both it will work the way you want. – Janick Fischer Feb 16 '18 at 16:16
  • 4
    [Reading around](https://stackoverflow.com/questions/30626030), people seem to frown upon using `key` in this way, saying it's not a pure way of using React. However their solution is to call `forceUpdate()` instead, which doesn't work; changing the value of `key` _does_ work, so I'm gonna go with that. Thanks! :) – teedyay Feb 19 '18 at 10:02
  • This works as intended. However the iframe flikers when reloaded. Is there any workaround? – Rakshit Arora Nov 16 '21 at 05:48
3

In case of Javascript frameworks and technologies, If you update the key, then it'll automatically reload the iFrame. So you just want to increase (or Random number) the value of key for your action.

state = {
    iframe_key: 0,
    iframe_url: 'https://www.google.com/maps' //Your URL here
}
iframeRefresh() {
    this.setState({iframe_key: this.state.iframe_key + 1});
}

public render() {
    return (
        <div>
            <button onClick={() => { this.iframeRefresh(); }}>Reload Iframe</button>
            <iframe key={this.state.iframe_key} src={this.state.iframe_url}> 
            </iframe>
        </div>
    );
}
Jopsy
  • 145
  • 1
  • 8
1
    <iframe key={props.location.key} />

use This "Router location Key" each click will get random value, whenever to navigate to here this value will get change then iframe will get the refresh

1

Updating the source causes a reload without causing a rerender.

import React, { useState, useRef } from 'react'

function renderIframe({src}){
    const iframeRef = useRef()
    return <>
               <iframe ref={iframeRef} src={src} >
               <span onClick={e => (iframeRef.current.src += '')}>Reload</span
           </>
}
                            
David Fridley
  • 165
  • 1
  • 10
0

You could create a new component which just loads you iframe. In your main component you load it and give it a update prop which you ignore in you iframe component. If you set the prop with a state variable, your component will reload. You can take a look at Diogo Sgrillo's answer for the setState method.

You could also check with shouldcomponentupdate() if the prop changed and only update if it changed.

Janick Fischer
  • 651
  • 7
  • 17
0

Maybe a bit late here :) Just a side note: When you update state based on previous state you should pass a function to setState:

resetIframe() {
    this.setState(prevState => {random: prevState.random + 1});
}
Freedruk
  • 437
  • 2
  • 4