0

I'm building an online gallery in React, and it requires an external script in order to work properly.

There are 2 main components, namely Home.js and Single.js. Home.js displays some categories the images are organized in, and the Single.js is the detail view of a category (it contains all the photos under a specific category). The Router looks like this:

    <Provider store={ store }>
        <Router
            forceRefresh={ false }>
            <div id="router">
                <Switch>
                    <Route exact path='/' render={ () => <MainLayout><Home /></MainLayout> } />
                    <Route exact path='/about' render={ () => <MainLayout><About /></MainLayout> } />
                    <Route path='/single/:id' render={ (props) => <MainLayout><Single {...props} /></MainLayout> } />
                </Switch>
            </div>
        </Router>
    </Provider> 

I am loading the script 'main.js' using this function:

appendScripts() {
    const main = document.createElement('script');
    main.src = '/js/main.js';
    main.async = true;
    main.id = 'main';
    document.body.appendChild(main);
}

Now the thing is that the script loads on the Home.js component, but it won't load on the Single.js component only the second time I access it through the home page (for the same category), even though it is appended in the DOM. And the same thing goes for accessing the home page through Single.js. If Single.js loads first, I need to access the Home.js 2 times through the Single.js for the script to load properly.

The components both have these functions called:

    componentDidMount() {
        this.appendScripts();
    }

    componentWillMount() {
        this.props.getImages(this.state.id);
        this.props.getCategory(this.state.id);
    }

Any thoughts?

2
  • I hope to understand the situation. Have you considered to 'import' the file instead of appending it? Commented Mar 16, 2018 at 17:06
  • Actually, I haven't. I'll try to do it now and return here with the result. Commented Mar 16, 2018 at 20:05

2 Answers 2

0

I have a similar use case as yours, it is on demand loading of Google's Recaptcha. The key idea to ensure script is loaded before rendering components which access the external script. Here is a simple example

  1. create a state named loading
  2. componentDidMount, append the script tag, set onload callback, and set src.
  3. when script loaded it calls onload to setState({ loading: false })
  4. do conditional rendering { !loading && <MyCompUseExternalScript/>}

i've copied the code here https://gist.github.com/kykean/29edc055e75a39bdcd329d3323f8bf0b The example uses recompose and is a HOC but the core idea is similar.

Sign up to request clarification or add additional context in comments.

Comments

0

My guess is that since ReactRouter doesn't actually refresh the page, the script is being cached and just presented a second time without being run. I would put the script into a function and then call it somewhere else, possibly in componentDidMount, or at least register a listener for when the script is loaded and run it.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.