I have a simple reducer, how do I bind this
from outside to use that inside the reducer this.teacherInstance
?
this.teachersDropMenu = this.plans.reduce(function (teacherIdArr, teacher) {
if (teacherIdArr.indexOf(teacher.teacherId) == -1) {
teacherIdArr.push(this.teacherInstance.getTeacherModelById(teacher.teacherId));
}
return teacherIdArr;
}, []);
I have a simple reducer, how do I bind this
from outside to use that inside the reducer this.teacherInstance
?
this.teachersDropMenu = this.plans.reduce(function (teacherIdArr, teacher) {
if (teacherIdArr.indexOf(teacher.teacherId) == -1) {
teacherIdArr.push(this.teacherInstance.getTeacherModelById(teacher.teacherId));
}
return teacherIdArr;
}, []);
Share
Improve this question
edited Dec 30, 2018 at 0:35
11684
7,52712 gold badges52 silver badges74 bronze badges
asked Dec 28, 2018 at 14:56
POVPOV
12k40 gold badges128 silver badges229 bronze badges
4
-
1
Have you tried using an arrow function
=>
instead of thefunction
keyword? – Kokodoko Commented Dec 28, 2018 at 14:59 -
2
Bind it to the function by using
.bind(this)
after the function. Or use avar self = this;
outside of the reduce loop and useself.teachInstance
. Or use an arrow function. Or alternatively, turn the logic around and use.map()
, which supports athis
argument as the second parameter and filter out the duplicates after. You could also make the reduction function a method ofthis
so you can usethis.plans.reduce( this.findTeacherModels );
or something. – Shilly Commented Dec 28, 2018 at 15:01 - @OPV see this hacks.mozilla/2015/06/es6-in-depth-arrow-functions – Sagar P. Ghagare Commented Dec 28, 2018 at 15:05
-
are you sure, that
this.teacherInstance.getTeacherModelById
returns a single id? which is possible to use withindexOf
? – Nina Scholz Commented Dec 28, 2018 at 15:13
3 Answers
Reset to default 8Using explicit binding with Function.prototype.bind
:
this.teachersDropMenu = this.plans.reduce(function (teacherIdArr, teacher) {
if (teacherIdArr.indexOf(teacher.teacherId) == -1) {
teacherIdArr.push(this.teacherInstance.getTeacherModelById(teacher.teacherId));
}
return teacherIdArr;
}.bind(this), []);
Using a closure/reference:
const self = this;
this.teachersDropMenu = this.plans.reduce(function (teacherIdArr, teacher) {
if (teacherIdArr.indexOf(teacher.teacherId) == -1) {
teacherIdArr.push(self.teacherInstance.getTeacherModelById(teacher.teacherId));
}
return teacherIdArr;
}, []);
Using an ES6 arrow function that doesn't have a this
of its own, preserving the "outer" this:
this.teachersDropMenu = this.plans.reduce((teacherIdArr, teacher) => {
if (teacherIdArr.indexOf(teacher.teacherId) == -1) {
teacherIdArr.push(this.teacherInstance.getTeacherModelById(teacher.teacherId));
}
return teacherIdArr;
}, []);
Use an ES6 arrow function as they work in lexical scope
, so this
is determined depending on "where" it is written:
this.teachersDropMenu = this.plans.reduce((teacherIdArr, teacher) => {
if (teacherIdArr.indexOf(teacher.teacherId) == -1) {
teacherIdArr.push(this.teacherInstance.getTeacherModelById(
teacher.teacherId));
}
return teacherIdArr;
}, []);
Also have a look here: How to access the correct `this` inside a callback?
If you can't use arrow functions
you can simply use the bind
method with the anonymous function like this:
this.teachersDropMenu = this.plans.reduce(function (teacherIdArr, teacher) {
if (teacherIdArr.indexOf(teacher.teacherId) == -1) {
teacherIdArr.push(this.teacherInstance.getTeacherModelById(
teacher.teacherId));
}
return teacherIdArr;
}.bind(this), []);
Another approach would be to store this
in another variable and use the lexical scope:
var that = this;
this.teachersDropMenu = this.plans.reduce(function (teacherIdArr, teacher) {
if (teacherIdArr.indexOf(teacher.teacherId) == -1) {
teacherIdArr.push(that.teacherInstance.getTeacherModelById(
teacher.teacherId));
}
return teacherIdArr;
}, []);
Both approaches are fine.