Binding to getInitialState? - javascript

Is it possible to bind to the getInitialState()?
BidLists = React.createClass({
getInitialState: function(s) {
return{
filteredID: this.props.data,
currentData: s
}
},
renderBidContent: function(s) {
return(
<div>{s.support_title}</div>
);
},
render: function() {
var cards = this.props.data.slice(0,25).map( (s, i) => {
return (
<div>
{this.getInitialState.bind(this,s)} // is this even possible?
</div>
);
});
var currentData = this.state.currentData;
return(
<div>{this.renderBidContent(currentData)}</div>
);
}
});
module.exports = BidLists;
Im getting:
cannot read property 'support_title' of undefined
I seem to not binding s properly. Any help? I'm using React v0.14
Reason behind this:
In the renderBidContent() there will be another function loop. That loop will test against s.id. I can achieve this in the BidList's render() but the output is twice and I dont want that.
I'm trying to do something like this but without a click method.

You can't do this, this isn't how bind works.
maybe you're looking for something like this
BidLists = React.createClass({
getInitialState: function(s) {
return{
filteredID: this.props.data
}
},
renderBidContent: function(s) {
return(
<div>{s.support_title}</div>
);
},
render: function() {
return this.props.data.slice(0,25).map( (s, i) => {
return <div>{this.renderBidContent(s)}</div>
});
}
});
How Bind Works
Bind doesn't actually bind the old function. It creates a new function and binds context or variables to it. Bind works similar to currying.
consider this function
function multiply(x, y){
return x * y
}
and now say I want to create a multiplyTwo function using the above function (we could also create our own but lets pretend multiply is an extremely complicated function).
Method 1, currying/closure.
function multiplyAny(num) {
return function(y){
return multiply(num, y);
}
}
var multiplyTwo = multiplyAny(2);
multiplyTwo(5); //this should give you 10
Method 2 bind
var multiplyTwo = multiply.bind(null, 2);
multiplyTwo(5); //this should give you 10
bind is like a special kind of curry and creates a new function with some of the variables already set. The first variable is the context (a.k.a this keyword)

Related

Spy function with elementary JavaScript syntax [duplicate]

The main reason why I want it is that I want to extend my initialize function.
Something like this:
// main.js
window.onload = init();
function init(){
doSomething();
}
// extend.js
function extends init(){
doSomethingHereToo();
}
So I want to extend a function like I extend a class in PHP.
And I would like to extend it from other files too, so for example I have the original init function in main.js and the extended function in extended.js.
With a wider view of what you're actually trying to do and the context in which you're doing it, I'm sure we could give you a better answer than the literal answer to your question.
But here's a literal answer:
If you're assigning these functions to some property somewhere, you can wrap the original function and put your replacement on the property instead:
// Original code in main.js
var theProperty = init;
function init(){
doSomething();
}
// Extending it by replacing and wrapping, in extended.js
theProperty = (function(old) {
function extendsInit() {
old();
doSomething();
}
return extendsInit;
})(theProperty);
If your functions aren't already on an object, you'd probably want to put them there to facilitate the above. For instance:
// In main.js
var MyLibrary = {
init: function init() {
}
};
// In extended.js
(function() {
var oldInit = MyLibrary.init;
MyLibrary.init = extendedInit;
function extendedInit() {
oldInit.call(MyLibrary); // Use #call in case `init` uses `this`
doSomething();
}
})();
But there are better ways to do that. Like for instance, providing a means of registering init functions.
// In main.js
var MyLibrary = (function() {
var initFunctions = [];
return {
init: function init() {
var fns = initFunctions;
initFunctions = undefined;
for (var index = 0; index < fns.length; ++index) {
try { fns[index](); } catch (e) { }
}
},
addInitFunction: function addInitFunction(fn) {
if (initFunctions) {
// Init hasn't run yet, remember it
initFunctions.push(fn);
} else {
// `init` has already run, call it almost immediately
// but *asynchronously* (so the caller never sees the
// call synchronously)
setTimeout(fn, 0);
}
}
};
})();
Here in 2020 (or really any time after ~2016), that can be written a bit more compactly:
// In main.js
const MyLibrary = (() => {
let initFunctions = [];
return {
init() {
const fns = initFunctions;
initFunctions = undefined;
for (const fn of fns) {
try { fn(); } catch (e) { }
}
},
addInitFunction(fn) {
if (initFunctions) {
// Init hasn't run yet, remember it
initFunctions.push(fn);
} else {
// `init` has already run, call it almost immediately
// but *asynchronously* (so the caller never sees the
// call synchronously)
setTimeout(fn, 0);
// Or: `Promise.resolve().then(() => fn());`
// (Not `.then(fn)` just to avoid passing it an argument)
}
}
};
})();
There are several ways to go about this, it depends what your purpose is, if you just want to execute the function as well and in the same context, you can use .apply():
function init(){
doSomething();
}
function myFunc(){
init.apply(this, arguments);
doSomethingHereToo();
}
If you want to replace it with a newer init, it'd look like this:
function init(){
doSomething();
}
//anytime later
var old_init = init;
init = function() {
old_init.apply(this, arguments);
doSomethingHereToo();
};
The other methods are great but they don't preserve any prototype functions attached to init. To get around that you can do the following (inspired by the post from Nick Craver).
(function () {
var old_prototype = init.prototype;
var old_init = init;
init = function () {
old_init.apply(this, arguments);
// Do something extra
};
init.prototype = old_prototype;
}) ();
Another option could be:
var initial = function() {
console.log( 'initial function!' );
}
var iWantToExecuteThisOneToo = function () {
console.log( 'the other function that i wanted to execute!' );
}
function extendFunction( oldOne, newOne ) {
return (function() {
oldOne();
newOne();
})();
}
var extendedFunction = extendFunction( initial, iWantToExecuteThisOneToo );
2017+ solution
The idea of function extensions comes from functional paradigm, which is natively supported since ES6:
function init(){
doSomething();
}
// extend.js
init = (f => u => { f(u)
doSomethingHereToo();
})(init);
init();
As per #TJCrowder's concern about stack dump, the browsers handle the situation much better today. If you save this code into test.html and run it, you get
test.html:3 Uncaught ReferenceError: doSomething is not defined
at init (test.html:3)
at test.html:8
at test.html:12
Line 12: the init call, Line 8: the init extension, Line 3: the undefined doSomething() call.
Note: Much respect to veteran T.J. Crowder, who kindly answered my question many years ago, when I was a newbie. After the years, I still remember the respectfull attitude and I try to follow the good example.
This is very simple and straight forward. Look at the code. Try to grasp the basic concept behind javascript extension.
First let us extend javascript function.
function Base(props) {
const _props = props
this.getProps = () => _props
// We can make method private by not binding it to this object.
// Hence it is not exposed when we return this.
const privateMethod = () => "do internal stuff"
return this
}
You can extend this function by creating child function in following way
function Child(props) {
const parent = Base(props)
this.getMessage = () => `Message is ${parent.getProps()}`;
// You can remove the line below to extend as in private inheritance,
// not exposing parent function properties and method.
this.prototype = parent
return this
}
Now you can use Child function as follows,
let childObject = Child("Secret Message")
console.log(childObject.getMessage()) // logs "Message is Secret Message"
console.log(childObject.getProps()) // logs "Secret Message"
We can also create Javascript Function by extending Javascript classes, like this.
class BaseClass {
constructor(props) {
this.props = props
// You can remove the line below to make getProps method private.
// As it will not be binded to this, but let it be
this.getProps = this.getProps.bind(this)
}
getProps() {
return this.props
}
}
Let us extend this class with Child function like this,
function Child(props) {
let parent = new BaseClass(props)
const getMessage = () => `Message is ${parent.getProps()}`;
return { ...parent, getMessage} // I have used spread operator.
}
Again you can use Child function as follows to get similar result,
let childObject = Child("Secret Message")
console.log(childObject.getMessage()) // logs "Message is Secret Message"
console.log(childObject.getProps()) // logs "Secret Message"
Javascript is very easy language. We can do almost anything. Happy JavaScripting... Hope I was able to give you an idea to use in your case.
Use extendFunction.js
init = extendFunction(init, function(args) {
doSomethingHereToo();
});
But in your specific case, it's easier to extend the global onload function:
extendFunction('onload', function(args) {
doSomethingHereToo();
});
I actually really like your question, it's making me think about different use cases.
For javascript events, you really want to add and remove handlers - but for extendFunction, how could you later remove functionality? I could easily add a .revert method to extended functions, so init = init.revert() would return the original function. Obviously this could lead to some pretty bad code, but perhaps it lets you get something done without touching a foreign part of the codebase.

Javascript object this is alway window

I've asked this in the past but still not understanding why my this is always window and not the calling object.
on the page there is button control:
<input type="button" value="Press Me" id="buttonPressMe" #click="pressMeClicked" />
This is the component and under methods is where I have functions:
pressMeClicked() is the function that gets called:
pressMeClicked: () => {
console.log(this.el)
var dd = this;
console.log('pressMeClicked');
}
The problem is this is not the component object in the pressMeClicked() function. It's always the window object. The code below shows how I add an event listener to the element. And either of the two options I used does call the pressMeClicked function. The only problem is that this is not the component obj but window:
const funcBind = function(obj, method, args = []){
return function(){
return method.apply(obj, args);
}
}
const funcProcess = (component, elements) => {
const fn = component.methods['pressMeClicked'];
const methodCall = funcBind(component, fn);
const elem = component.selector('#buttonPressMe');
elem.addEventListener('click', () => {
// Tried this
fn.bind(component)()
// Tried this also
methodCall();
}
}
When I step into the function methodCall(), obj is the component.
Any help would greatly be appreciated
pressMeClicked is an arrow function, which is a non-bound function. Because of that, this will always refer to the value of this inside the lexical scope of its containing function. To fix this change the arrow function definition to a regular function (method):
// Instead of:
pressMeClicked: () => {
// ...
}
// Do this:
pressMeClicked() {
// ...
}
// or:
pressMeClicked: function() {
// ...
}

how to access vairables outside of map function in js and jsx in a React component

var PieceList = React.createClass({
render: function() {
var pieces;
if (this.props.pieces && this.props.onDeletePiece2) {
var pieces = this.props.pieces.map(function (piece) {
return (
<Piece pieceData={piece} onDeletePiece3={this.props.onDeletePiece2} />
)
});
}
return (
<div className="piecesTable">
{pieces}
</div>
);
}
});
I'm stumped as to how to get this to work. The problem is that {this.props} is not available inside of the map function.
Would a foreach be better here? stumped, pls halp!
map is just a regular JavaScript method (see Array.prototype.map). It can take an argument that sets the context (.map(callback[, thisArg])):
var PieceList = React.createClass({
render: function() {
var pieces;
if (this.props.pieces && this.props.onDeletePiece2) {
var pieces = this.props.pieces.map(function (piece) {
return (
<Piece pieceData={piece} onDeletePiece3={this.props.onDeletePiece2} />
)
}, this); // need to add the context
}
return (
<div className="piecesTable">
{pieces}
</div>
);
}
});
I would suggest going back and reading about this in JavaScript. When you pass an anonymous function to most methods (like .map, .forEach, etc.), it takes the global context (which is almost always window). If you pass in this as the last argument, since that this is referring to the class you just created with React.createClass, it'll set the correct context.
In other words, the way you were trying to do it was access window.props, which obviously doesn't exist. I'd if you opened your console to debug, you'd see the error Object Window doesn't have the property "props" or something very obfuscated.
EDIT 2: React 0.14.x
You can now define stateless functional components for components that do not require complex lifecycle event hooks or internal state
const PieceList = ({pieces, onDeletePiece2}) => {
if (!onDeletePiece2) return;
return (
<div className="piecesTable">
{pieces.map(x => (
<Pieces pieceData={x} onDeletePiece3={onDeletePiece2}>
))}
</div>
);
};
EDIT 1: ES6
As ES6 continues to become more prominent, you can also avoid nitpicky context issues by using an ES6 arrow function.
class PieceList extends React.Component {
renderPiece(piece) {
return <Piece pieceData={piece} onDeletePiece3={this.props.onDeletePiece2} />;
}
render() {
if (!this.props.onDeletePiece2) return;
return (
<div className="piecesTable">
{this.props.pieces.map(piece => this.renderPiece(piece))}
<div>
);
}
}
To get this to run in most environments, you'd need to "transpile" it using something like babel.js
The quick answer is that you need to bind the proper this to the map callback by passing this as the second arg
this.props.pieces.map(..., this);
This might be a better way to write your component tho
var PieceList = React.createClass({
renderPiece: function(piece) {
return <Piece pieceData={piece} onDeletePiece3={this.props.onDeletePiece2} />;
},
render: function() {
if (!this.props.onDeletePiece2) return;
return (
<div className="piecesTable">
{this.props.pieces.map(this.renderPiece, this)}
</div>
);
}
});
Regarding your comment about map
var x = {a: 1, b: 2};
['a', 'b'].map(function(key) {
// `this` is set to `x`
// `key` will be `'a'` for the first iteration
// `key` will be `'b'` for the second iteration
console.log(this[key]);
}, x); // notice we're passing `x` as the second argument to `map`
Will output
// "1"
// "2"
Notice how the second argument to map can set the context for the function. When you call this inside the function, it will be equal to the second variable that was sent to map.
This is JavaScript basics and you should definitely read up more here
Are you using a transpiler -- something like Babel? If so, this code will work fine:
if (this.props.pieces && this.props.onDeletePiece2) {
var pieces = this.props.pieces.map((piece, i) => {
return (
<Piece pieceData={piece} onDeletePiece3={this.props.onDeletePiece2} key={i}/>
)
});
...
If you can't use a transpiler, you could do this:
if (this.props.pieces && this.props.onDeletePiece2) {
var that = this;
var pieces = that.props.pieces.map( function(piece, i) {
return (
<Piece pieceData={piece} onDeletePiece3={that.props.onDeletePiece2} key={i}/>
)
})
...

How can rewrite function instead of reference?

var BigObject = (function() {
function deepCalculate(a, b, c) {
return a + b + c;
}
function calculate(x) {
deepCalculate(x, x, x);
}
return {
calculate: calculate,
api: {
deepCalculate: deepCalculate
}
}
})();
This is basic self executing function with private function I keep in api.
The problem I have is that now I can't overwrite deepCalculate from the outside of the function.
How is that a problem? I use Jasmine and want to test if function was called. For example:
spyOn(BigObject, 'calculate').andCallThrough();
expect(BigObject.api.deepCalculate).toHaveBeenCalled();
fails. However as I debug, I am sure that Jasmine binds BigObject.api.deepCalculate as a spy, however from the inside calculate still calls original deepCalculate function and not the spy.
I would like to know how can I overwrite the function and not just a reference for it.
The simple answer would be:
(function ()
{
var overWriteMe = function(foo)
{
return foo++;
},
overWrite = function(newFunc)
{
for (var p io returnVal)
{
if (returnVal[p] === overWriteMe)
{//update references
returnVal[p] = newFunc;
break;
}
}
overWriteMe = newFunc;//overwrite closure reference
},
returnVal = {
overWrite: overWrite,
myFunc: overWriteMe
};
}());
Though I must say that, I'd seriously think about alternative ways to acchieve whatever it is you're trying to do. A closure, IMO, should be treated as a whole. Replacing parts of it willy-nilly will soon prove to be a nightmare: you don't know what the closure function will be at any given point in time, where it was changed, what the previous state was, and why it was changed.
A temporary sollution might just be this:
var foo = (function()
{
var calc = function(x, callback)
{
callback = callback || defaultCall;
return callback.apply(this, [x]);
},
defaultCall(a)
{
return a*a+1;
},
return {calc: calc};
}());
foo(2);//returns 5
foo(2,function(x){ return --x;});//returns 1
foo(2);//returns 5 again
IMO, this is a lot safer, as it allows you to choose a different "internal" function to be used once, without changing the core behaviour of the code.

Javascript: Extend a Function

The main reason why I want it is that I want to extend my initialize function.
Something like this:
// main.js
window.onload = init();
function init(){
doSomething();
}
// extend.js
function extends init(){
doSomethingHereToo();
}
So I want to extend a function like I extend a class in PHP.
And I would like to extend it from other files too, so for example I have the original init function in main.js and the extended function in extended.js.
With a wider view of what you're actually trying to do and the context in which you're doing it, I'm sure we could give you a better answer than the literal answer to your question.
But here's a literal answer:
If you're assigning these functions to some property somewhere, you can wrap the original function and put your replacement on the property instead:
// Original code in main.js
var theProperty = init;
function init(){
doSomething();
}
// Extending it by replacing and wrapping, in extended.js
theProperty = (function(old) {
function extendsInit() {
old();
doSomething();
}
return extendsInit;
})(theProperty);
If your functions aren't already on an object, you'd probably want to put them there to facilitate the above. For instance:
// In main.js
var MyLibrary = {
init: function init() {
}
};
// In extended.js
(function() {
var oldInit = MyLibrary.init;
MyLibrary.init = extendedInit;
function extendedInit() {
oldInit.call(MyLibrary); // Use #call in case `init` uses `this`
doSomething();
}
})();
But there are better ways to do that. Like for instance, providing a means of registering init functions.
// In main.js
var MyLibrary = (function() {
var initFunctions = [];
return {
init: function init() {
var fns = initFunctions;
initFunctions = undefined;
for (var index = 0; index < fns.length; ++index) {
try { fns[index](); } catch (e) { }
}
},
addInitFunction: function addInitFunction(fn) {
if (initFunctions) {
// Init hasn't run yet, remember it
initFunctions.push(fn);
} else {
// `init` has already run, call it almost immediately
// but *asynchronously* (so the caller never sees the
// call synchronously)
setTimeout(fn, 0);
}
}
};
})();
Here in 2020 (or really any time after ~2016), that can be written a bit more compactly:
// In main.js
const MyLibrary = (() => {
let initFunctions = [];
return {
init() {
const fns = initFunctions;
initFunctions = undefined;
for (const fn of fns) {
try { fn(); } catch (e) { }
}
},
addInitFunction(fn) {
if (initFunctions) {
// Init hasn't run yet, remember it
initFunctions.push(fn);
} else {
// `init` has already run, call it almost immediately
// but *asynchronously* (so the caller never sees the
// call synchronously)
setTimeout(fn, 0);
// Or: `Promise.resolve().then(() => fn());`
// (Not `.then(fn)` just to avoid passing it an argument)
}
}
};
})();
There are several ways to go about this, it depends what your purpose is, if you just want to execute the function as well and in the same context, you can use .apply():
function init(){
doSomething();
}
function myFunc(){
init.apply(this, arguments);
doSomethingHereToo();
}
If you want to replace it with a newer init, it'd look like this:
function init(){
doSomething();
}
//anytime later
var old_init = init;
init = function() {
old_init.apply(this, arguments);
doSomethingHereToo();
};
The other methods are great but they don't preserve any prototype functions attached to init. To get around that you can do the following (inspired by the post from Nick Craver).
(function () {
var old_prototype = init.prototype;
var old_init = init;
init = function () {
old_init.apply(this, arguments);
// Do something extra
};
init.prototype = old_prototype;
}) ();
Another option could be:
var initial = function() {
console.log( 'initial function!' );
}
var iWantToExecuteThisOneToo = function () {
console.log( 'the other function that i wanted to execute!' );
}
function extendFunction( oldOne, newOne ) {
return (function() {
oldOne();
newOne();
})();
}
var extendedFunction = extendFunction( initial, iWantToExecuteThisOneToo );
2017+ solution
The idea of function extensions comes from functional paradigm, which is natively supported since ES6:
function init(){
doSomething();
}
// extend.js
init = (f => u => { f(u)
doSomethingHereToo();
})(init);
init();
As per #TJCrowder's concern about stack dump, the browsers handle the situation much better today. If you save this code into test.html and run it, you get
test.html:3 Uncaught ReferenceError: doSomething is not defined
at init (test.html:3)
at test.html:8
at test.html:12
Line 12: the init call, Line 8: the init extension, Line 3: the undefined doSomething() call.
Note: Much respect to veteran T.J. Crowder, who kindly answered my question many years ago, when I was a newbie. After the years, I still remember the respectfull attitude and I try to follow the good example.
This is very simple and straight forward. Look at the code. Try to grasp the basic concept behind javascript extension.
First let us extend javascript function.
function Base(props) {
const _props = props
this.getProps = () => _props
// We can make method private by not binding it to this object.
// Hence it is not exposed when we return this.
const privateMethod = () => "do internal stuff"
return this
}
You can extend this function by creating child function in following way
function Child(props) {
const parent = Base(props)
this.getMessage = () => `Message is ${parent.getProps()}`;
// You can remove the line below to extend as in private inheritance,
// not exposing parent function properties and method.
this.prototype = parent
return this
}
Now you can use Child function as follows,
let childObject = Child("Secret Message")
console.log(childObject.getMessage()) // logs "Message is Secret Message"
console.log(childObject.getProps()) // logs "Secret Message"
We can also create Javascript Function by extending Javascript classes, like this.
class BaseClass {
constructor(props) {
this.props = props
// You can remove the line below to make getProps method private.
// As it will not be binded to this, but let it be
this.getProps = this.getProps.bind(this)
}
getProps() {
return this.props
}
}
Let us extend this class with Child function like this,
function Child(props) {
let parent = new BaseClass(props)
const getMessage = () => `Message is ${parent.getProps()}`;
return { ...parent, getMessage} // I have used spread operator.
}
Again you can use Child function as follows to get similar result,
let childObject = Child("Secret Message")
console.log(childObject.getMessage()) // logs "Message is Secret Message"
console.log(childObject.getProps()) // logs "Secret Message"
Javascript is very easy language. We can do almost anything. Happy JavaScripting... Hope I was able to give you an idea to use in your case.
as I understand it, you are trying to fetch the applications connected to the user account. You can do this by making a request on the API, I don't know if discord.js covers this part of the API
endpoint: https://discord.com/api/users/#me/connections
Request type: GET Header:
Authorization: "Beareryou token"
response: [
{...}
]
Use extendFunction.js
init = extendFunction(init, function(args) {
doSomethingHereToo();
});
But in your specific case, it's easier to extend the global onload function:
extendFunction('onload', function(args) {
doSomethingHereToo();
});
I actually really like your question, it's making me think about different use cases.
For javascript events, you really want to add and remove handlers - but for extendFunction, how could you later remove functionality? I could easily add a .revert method to extended functions, so init = init.revert() would return the original function. Obviously this could lead to some pretty bad code, but perhaps it lets you get something done without touching a foreign part of the codebase.

Categories

Resources