I am trying called the react component's function from a javascript function. On the initial stage, I want to call my function which is declared in react component but rather than a call from react I need to call it from a javascript function.
I know how to call a javascript function from react function. like below
Javascript
<script type="text/javascript">
function test(){
alert('Function from index.html');
}
</script>
React
componentWillMount() {
window.test();
}
But in my case, I want a totally reverse process, need to call react function from a javascript due to certain plugin initialization.
I went through other related topics but don't get an exact answer. so how should I do this?
You can can assign a function to the window object as a function and call that from your script. So essentially you would do the following:
componentWillMount() {
window.reactFunction = () => {
console.log('Test');
}
}
Then call it from your script like so:
<script type="text/javascript">
function test(){
window.reactFunction()
}
</script>
Admittedly I have no idea how exactly you plan to use this but this could be one way of accomplishing what you want by utilizing the global window object. The second part would realistically need some way of determining whether the react component has mounted (in a non trivial example), or just check for the existence of the method before calling it.
Related
I have a hook that adds a header tag in order to load a script, but in case two components are using it, the hook could fall into the case that the header is added twice.
There are several ways to avoid this. Two of them could be:
Use a provider, not a hook that several components could call. Actually I don't want this, I want a hook because at most two components will use it, and in some cases I don't even need it;
The hook calls a function called const addHeaderTag = () => {...}. I could add a property to it and check if the function is called just once, otherwise return silently. It could be safe because the function is defined by me and I control the function object, plus javascript is monothread and concurrency is out of scope;
I could add an id to the header so as to check if it's on the DOM already. I'd avoid it in order to not access the DOM too much
Do you see other better ways? Do you see any problem to the solutions I had in mind?
A solution for this would be using a variable outside of your custom hook to check whether or not your hook is already called
import { useEffect } from "react";
let isCalled = false;
export const useOnce = () => {
useEffect(() => {
if (!isCalled) {
// do this only once, call your function here
console.log("hey there");
isCalled = true;
}
}, []);
return isCalled;
};
The reason this works is because when you import the same module multiple times, the code in that module is still only evaluated once.
That means isCalled in this case is only initialized once, so we can depend on it to check/set the value accordingly for the entire app.
Live example
I have a function, for example, boot:
function boot(){
return("Arbitrary value");
}
Like you can listen for the onload, onclick, onkeydown, etc., is there any easy way (Without modifying the boot function) to do a sort of onboot?
[EDIT]
Seeing confusion, I will explain more.
Imagine a script that I have no control over is imported. The boot function is randomly called, and when the boot function is called, the script I have no control over wants to do something. Whoever wrote the script would like to do something like this: onboot = function(){consoe.log("whatever")}
Is this something that is possible?
Thanks,
-Dylan
You can do something similar to what you want, but not without modifying boot. You can change the boot function so that you can register event handlers that are called whenever boot is called with something like this:
var callbacks = [];
function boot() {
callbacks.forEach(function(f) { f(); });
return "Arbitrary value";
}
function registerBootCallback(f) {
callbacks.push(f);
}
Note that the boot function doesn't need to explicitly call the handlers.
If you can't modify the boot function itself, but you control everywhere it is called, create a new function that calls boot and all the callbacks, and call that instead of boot directly. If you can't change boot and don't control everywhere it is called, (and some kind of callback mechanism doesn't already exist) then you are out of luck.
There are also probably libraries that make this a little easier, and allow you to do things like event propagation.
You can overwrite the boot function in your code without changing it in the script.
var real_boot = boot
boot = function () {
// insert your code
real_boot()
}
See this documentation. My solution creates a custom event, which will be triggered by the calling function.
Let's say we have functions base and called, base calling called once complete:
var onboot = new Event('onboot');
document.addEventListener('onboot' called);
function base () {
// I do stuff
console.log("base");
document.dispatchEvent(onboot);
}
function called () {
// do stuff here
console.log("called");
}
So if you call base now, you'll get this result:
If the function is globally accessible. You can overwrite the function with your own function and then call old function inside your own function.
Eg
other-lib.js
function boot(){
//Do something internally that you dont have control over
}
your-file.js
var oldBoot = boot;
function boot(){
oldBoot.call(this, arguments);
//Do your stuff here
}
I want to call jquery function in side of java script. My code is:
<script type="text/javascript">
function calljs(){
getUserMail(usermMail);
}
$(function() {
function getUserMail(usermMail) {
***some code*****
}
});
</script>
I got error from browser console:
ReferenceError: getUserMail is not defined.
How to solve this problem?
As far as i understand, the method is not defined when the method is being called. So define it before it is getting called
<script type="text/javascript">
function getUserMail(usermMail) {
***some code*****
}
function calljs(){
getUserMail(usermMail);
}
$(function() {
//
});
</script>
hope it helps
If it is really compulsory to put the function with in the jquery's ready callback (which I don't think is compulsory) use the following way
<script type="text/javascript">
var getUserMail = null;
function calljs(){
if ( null !== getUserMail ) {
getUserMail(usermMail);
}
}
$(function() {
getUserMail = function (usermMail) {
***some code*****
}
});
</script>
You can simply do ,
$(document).ready(function(event) {
getUserMail(usermMail);
});
and define it like ,
function getUserMail(usermMail){
. . .
}
or using jquery ,
$(document).on('click', ".selector", function);
trigger a function on an event
getUserMail is not defined in a scope that is accessible to calljs. This is why you get the ReferenceError; in the context in which you tried to invoke getUserMail there was no function with that name available.
// At this point nothing is defined
function calljs(){
getUserMail(usermMail);
}
// now calljs is defined as a global and can be invoked from anywhere
$(function() { // this line is calling a function named $ (an alias for jQuery)
// and passing it an anonymous function as a parameter.
function getUserMail(usermMail) { // This function is being defined inside
// the scope of the anonymous function,
// it can be used anywhere inside the
// anonymous function but not outside it.
// ***some code*****
}
});
// we are now outside the scope of the anonymous function,
// getUserMail is no longer in our scope and can't be called from here.
The easiest and likely best solution for most situations would be to make sure that any functions that call each other are in the same scope.
From what I can tell you don't really need calljs, you were just trying to use it to poke a hole into the scope of the anonymous function where getUserMail is defined.
Instead you should probably get rid of calljs and move any code that is calling getUserMail inside the ready callback. If getUserMail needs to wait for the ready callback to be fired before you call it, any code that invokes it also should be inside the ready callback too. (Things like event handlers that call it should already be inside the ready callback anyway.)
If there is a reason that you can't move it into the ready callback, such as something in another .js file needs to be able to call it etc, your application might be too complicated to be realistically maintained as jQuery soup. It might be worth the effort to port it to a framework such as Ember or Angular.
Also so you know, there is no need to use the type attribute on your script tags. JavaScript is the only language that has wide support in the browser and all browsers default to using JavaScript for script tags.
I have a script that I didn't write already running on a page. I'd like to, in a script I did write, be able to execute a function from the original script. Here's a simplified example of what I'm trying to do:
(function ($) {
$.fn.myExistingFunction = function (options) {
function doMyThing(text) {
alert(text);
}
}
}(jQuery));
jQuery(document).ready(function($) {
$.fn.myExistingFunction.doMyThing("alert text");
});
However, when I run this, I get the console output:
Uncaught TypeError: Object function (options) {
function doMyThing(text) {
alert(text);
}
} has no method 'doMyThing'
But it clearly has the method! I can see it right there. What am I getting wrong here?
You can only access that method from the scope of the plugin function. It is not defined in the global scope.
So you can't call that function. All you can do in your code is call functions that are available through what's called the scope chain where the function is called. In your case that is everything that is either defined in your function($){} or in global scope. But the function in the plugin is neither.
When you call $.fn.myExistingFunction.doMyThing you are treating doMyThing like an field in the myExistingFunction object. But actually it is defined inside the function. Maybe this code makes it clearer:
$.fn.myExistingFunction = function (options) {
var doMyThing = function(text) {
alert(text);
}
var hi = "hello";
}
In hi and doMyThing are local variables in the scope of myExistingFunction. If the plugin wasn't designed to expose the functionality to external code you can't access the variables.
An example of a plugin that was designed to expose some of its internal functions would be the jQuery UI datepicker (documentation). It needs functions like parseDate and formatDate interally, but these utility functions are likely to be useful for general development as well, which is why they have been added to the datepicker object explicitly.
I think your code needs a major rewriting, 'cause as it is it will never work, in fact your function doMyThing is not a property of $.fn.myExistingFunction, it is simply declared inside of it, and due to how the scope works in javascript, you'll never be able to call it.
When calling a Javascript function, it seems like JS gives priority to functions without parameters first, even if I have the same function name with parameters.
The strange behavior only happens in the following scenario:
I have a an HTML page with embedded Javascript, like this:
//Javascript in the page
function testAbc(){
alert('testAbc no params');
}
//Javascript in common.js
function testAbc(x){
alert('testAbc with param:'+x);
}
function testAbcFunc(x){
testAbc(x);
}
Now from somewhere in the page, im calling testAbcFunc from the common.js expecting it to call testAbc with parameter which is the common function. But strangely, JS calls back the function in the original page without params!!
I have been debugging this bug fore few hours now, and i tried this short code to reproduce the bug, it does happen each time.
NOTE: if all functions are in the same page, the correct function (with params) will be called, but when ther are split between the page and the JS file. JS seems to give priority to the function in the page even though is doesn't have parameter
JavaScript does not support method overloading based on parameters. It simply uses the last-defined function if multiple functions have the same name. The version in the page will override the included version. When it worked for you, I assume that the include version (with the argument signature) was inlined after the original.
JavaScript doesn't have overloaded function. It doesn't care about signatures, it calls functions solely by names and nothing else. It is strange that later function does not completely hide the first one but well, there's no spec about that behaviour.
So just don't do that, check the number of params with arguments.length inside the function and don't try to use overloading which will never work.
function testAbc(){
if (arguments.length == 0) {
alert('testAbc no params');
} else {
var x = arguments[0];
alert('testAbc with param:'+x);
}
}
There is no function overloading in JavaScript. If you are defining a function with two times with diffrent number of parameters the last one to be defined will be called.
Also, you should be namespacing your JavaScript.
Like so:
var common = {
testABC: function () {
//Stuff
}
};
Then call testABC like this
common.testABC();