react-async-script
react-async-script copied to clipboard
How do you pass params to the URL?
Hi,
In the example shown, the URL is known upfront and hardcoded. Is it possible to pass in props into the wrapper that helps determine what the URL is and then inject that URL being used?
In my use case, bing maps api, I need to add in query params to set the Language or local.
example of what i'm looking for.
<WrapperComponent urlProps={} {… componentProps} />
Then in the WrapperComponent it takes the url props and builds the URL that is injected into the default.
export default AsyncScriptLoader(BingMapWidget, URL, { callbackName: callbackName, globalName: globalName, });
However, its not clear to me if it's possible to expose the wrapper to take in those params so then i can run a method to compute the URL and spit it back to the AsyncScriptLoader
Also i notice that you are attaching to the global scope. What happens if you launch two instances of the wrapped components. Would there be issues since they will share the same callback?
Thanks, Derek
Hi!
Also i notice that you are attaching to the global scope. What happens if you launch two instances of the wrapped components. Would there be issues since they will share the same callback?
So if they have the same url they will attach to the same script and everything is fine. It attaches to global scope because most of the libraries that load asynchronous attach something in the global scope, so it has to pass it through properly.
If they have different urls and they both attach to the same object, I don't see how that could work.
Also i notice that you are attaching to the global scope. What happens if you launch two instances of the wrapped components. Would there be issues since they will share the same callback?
In my use case, bing maps api, I need to add in query params to set the Language or local.
The latest version support a function as the getScriptUrl parameter. Which would allow you to change thing at run time. The getUrl function is called on componentDidMount
Thanks for the response.
I notice that there are the two examples load up the values differently.
export default makeAsyncScriptLoader(URL, {
callbackName: callbackName,
globalName: globalName,
})(ReCAPTCHA);
While the other one on NPM https://www.npmjs.com/package/react-async-script
export default makeAsyncScriptLoader(ReCAPTCHA, URL, {
callbackName: callbackName,
globalName: globalName,
});
When I step through the library and use the first example, I notice that I get an exception thrown
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
Is the first method valid?
- Any suggestion on how to debug why the call back is not being made. This is the script tag that i'm trying to load. It's suppose to trigger onMapLoaded. However, it never hits that break point.
https://www.bing.com/api/maps/mapcontrol?setMkt=en-us&setLang=en-us&callback=onMapLoaded
url based off code example: https://github.com/Microsoft/BingMapsV8CodeSamples/blob/master/Samples/Map/Localize%20the%20Map%20(en-GB).html
In the example you have, you associate the callback in two locations. One in the Url and the other as parameter into the library. What does the parameter in the library do and where does the callback need to live? Is it in the wrapper?
Thanks!
@darewreck54 so first method, is the next API. It's not published yet! It's part of the upcoming 1.0 release, should've probably made a 1.0 branch instead of merging to master. Here is the documentation that works with the current version: https://github.com/dozoisch/react-async-script/blob/d86c42cdefe49a71ae71d52109dcab143217ebe4/README.md
Sorry about this confusion!
About the callback:
The callback name in the url is used by the library you are loading, in this case bing maps. The callback name passed to react-async-script is used to register a global callback so that it can receive the load event from Bing. So the names need to match :)
The first thing i did was validate the the https://www.bing.com/api/maps/mapcontrol?setMkt=en-us&setLang=en-us&callback=onMapLoaded was valid in loading and making the callback. I achieve this by copying that example on in https://github.com/Microsoft/BingMapsV8CodeSamples/blob/master/Samples/Map/Localize%20the%20Map%20(en-GB).html an debug the code to make sure the callback is made.
So I know for sure the url is valid. However in my use case, I'm not seeing the call back triggered at all. The code is pretty straight forward:
import AsyncScriptLoader from 'react-async-script';
class BingMapWrapper extends React.Component {
constructor(props) {
super(props);
}
private onLoad(): void {
console.log("script loaded");
}
public onMapLoaded(): void {
console.log("Map onMapLoaded loaded");
}
public render(): any {
const callbackName: string = 'onMapLoaded';
conse url: string = 'https://www.bing.com/api/maps/mapcontrol?setMkt=en-us&setLang=en-us&callback=onMapLoaded'
const Component: any = AsyncScriptLoader(BingMap, url, {
callbackName: callbackName,
globalName: "tempName",
exposeFuncs: ['method1', 'method2'],
});
return <Component asyncScriptOnLoad={this.onLoad} {...this.props}/>;
}
}
class BingMap extends React.Component {
public onMapLoaded() {
console.log("bingMapWrapper called");
}
}
In this example, I'm not see how the class method is mapped to the global part. Am i doing it wrong? I would expect either one of the onMapLoaded to be triggered?
In the example, I don't really see the callback implemented. Is there a specific way it should be done?
The onLoad() does get triggered thou. Also the reason why i have it like this is because the BingMapWrapper takes in a para via prop to inject into the Url. I just didn't show it in this example.
Thanks, Derek
react-async-script puts the callbackName
on window
for you, window[callbackName]
and assigns an internal callback to trigger after it has loaded. here
After the script loads an internal setState
is called to trigger a re-render. so your <BingMap />
component will be called with props <BingMap tempName={window['tempName']} />
, code
So you can either check in BingMap
if props.tempName !== undefined
then do map stuff or do something when asyncScriptOnLoad
fires.
-
the
callbackName
string option needs to match the callback name in the url query.&callback=onMapLoaded
that is all. -
the only callback fired after the script has loaded that the user currently has access to is the
asyncScriptOnLoad
which looks like you are using above. is that one firing correctly?
I too apologize for the confusion in the readme on master. We are working towards a v1.0.0
release and @dozoisch is correct a branch would have been best.
@hartzis AsyncScriptOnLoad does get called and I see the setState trigger. However, when I look at the code
window[globalName] is always undefined. When I actually look at the source code, I never see it set.
I put a break point in both the BinMap's constructor and componentWillReceiveProps(), and the props.[globalName] is always undefined even when the onload method gets called.
the globalName
needs to be the name of the global that the script loads to.
for google recaptcha it is always window.grecaptcha
. doc
for bing maps it appears to be Microsoft
so it is accessible via window.Microsoft
.
Which means you want to use globalName = 'Microsoft'
and your component will get passed a props.Microsoft
object when the bing maps script loads. microsoft bing ref docs
I got it working in this example codesandbox, please give it a try and let us know. Example code sandbox: https://codesandbox.io/s/nwwo3wlyo0