Cannot read property 'setState' of undefined ReactJS - javascript

I am trying to set the state in React inside my function, however I get an error message stating: Cannot read property 'setState' of undefined.
Below is my code, I call the state in the constructor then I am setting the state in the addTimes function and binding this to that function, however I am still getting the error.
class Settings extends React.Component {
constructor(props) {
super(props);
this.state = {
times: []
};
}
render(){
Array.prototype.remove = function() {
var what, a = arguments, L = a.length, ax;
while (L && this.length) {
what = a[--L];
while ((ax = this.indexOf(what)) !== -1) {
this.splice(ax, 1);
}
}
return this;
};
var currentTicked = [];
var times =[]
function addTimes(id){
var index = times.indexOf(id);
if (!times.includes(id)) {
$("input:checkbox[name=time]:checked").each(function(){
currentTicked.push($(this).val());
times = times.concat(currentTicked)
times = jQuery.unique(times);
});
} else if(times.includes(id)){
times.remove(id)
}
console.log(times);
addTimes = () => {
this.setState({
times: times
});
}
}

you haven't bound the function to the class. try doing
addTimes = (id) => {
// code here
}
in the component class

Try with an arrow function:
addTimes = id => {
var index = times.indexOf(id);
if (!times.includes(id)) {
$("input:checkbox[name=time]:checked").each(function(){
currentTicked.push($(this).val());
times = times.concat(currentTicked)
times = jQuery.unique(times);
});
} else if(times.includes(id)){
times.remove(id)
}
console.log(times);
addTimes = () => {
this.setState({
times: times
});
}
}
Or, bind thisin addTimesfunction like this :
constructor(props) {
super(props);
this.state = {
times: []
this.addTimes = this.addTimes.bind(this);
};
}

better to use es6 syntax. try with below code.
class Settings extends React.Component {
constructor(props) {
super(props);
this.state = {
times: []
};
let times = [];
let currentTicked = [];
this.addTimes = this.addTimes.bind(this);
}
addTimes(id) {
let index = times.indexOf(id);
if (!times.includes(id)) {
$("input:checkbox[name=time]:checked").each(function(){
currentTicked.push($(this).val());
times = times.concat(currentTicked)
times = jQuery.unique(times);
});
} else if(times.includes(id)){
times.remove(id)
}
this.setState({
times: times
});
}
render(){
this.addTimes;
return (
Array.prototype.remove = function() {
var what, a = arguments, L = a.length, ax;
while (L && this.length) {
what = a[--L];
while ((ax = this.indexOf(what)) !== -1) {
this.splice(ax, 1);
}
}
return this;
}
);
}
}

Related

How to create a class that has a property of another class in TypeScript?

I am creating a web application that has a Competitor, hence the class Competitor, and a poll that will join 2 Competitors, hence the class VotingPoll. Here are the classes in JS:
export class Competitor {
constructor(_id, _name, easy, hard, tematicas, random_score, min1, min2, deluxe, replica) {
this._id = _id;
this._name = _name;
this.easy = easy;
this.hard = hard;
this.tematicas = tematicas;
this.random_score = random_score;
this.min1 = min1;
this.min2 = min2;
this.deluxe = deluxe;
this.replica = replica;
}
get id() {
return this._id;
}
get name() {
return this._name;
}
get_sum(mode) {
if (mode === '_name' || mode === '_id') {
throw new Error("mode can't be equal to 'name' nor 'id'");
}
let i = 0;
this[mode].forEach((j) => {
if (j !== 9) {
i += j;
}
});
return i;
}
get_total() {
return (this.get_sum('easy') +
this.get_sum('hard') +
this.get_sum('tematicas') +
this.get_sum('random_score') +
this.get_sum('min1') +
this.get_sum('min2') +
this.get_sum('deluxe'));
}
serialize() {
return JSON.stringify({
id: this._id,
name: this._name,
easy: this.easy,
hard: this.hard,
tematicas: this.tematicas,
random_score: this.random_score,
min1: this.min1,
min2: this.min2,
deluxe: this.deluxe,
replica: this.replica,
});
}
static unserialize(data) {
const newData = JSON.parse(data);
return new Competitor(newData.id, newData.name, newData.easy, newData.hard, newData.tematicas, newData.random_score, newData.min1, newData.min2, newData.deluxe, newData.replica);
}
}
export class VotingPoll {
constructor(_id, comp_1, comp_2) {
this._id = _id;
this.comp_1 = comp_1;
this.comp_2 = comp_2;
}
get id() {
return this._id;
}
get_winner(replica = false) {
const comp_1 = this.comp_1;
const comp_2 = this.comp_2;
// Case replica
if (replica) {
if (comp_1.get_sum('replica') === comp_2.get_sum('replica') ||
Math.abs(comp_1.get_sum('replica') - comp_2.get_sum('replica')) < 6) {
return 'Réplica';
}
const max_num = Math.max(comp_1.get_sum('replica'), comp_2.get_sum('replica'));
return max_num === comp_1.get_sum('replica') ? comp_1.name : comp_2.name;
}
// Normal case
if (comp_1.get_total() === comp_2.get_total() || Math.abs(comp_1.get_total() - comp_2.get_total()) < 6) {
return 'Réplica';
}
const max_num = Math.max(comp_1.get_total(), comp_2.get_total());
return max_num === comp_1.get_total() ? comp_1.name : comp_2.name;
}
serialize() {
return JSON.stringify({
id: this._id,
comp_1: this.comp_1,
comp_2: this.comp_2,
});
}
static unserialize(data) {
const newData = JSON.parse(data);
return new VotingPoll(newData.id, newData.comp_1, newData.comp_2);
}
}
The problem is that, when calling poll.get_winner(), JS doesn't know that comp_1 and comp_2 are of type Competitor, and that they do have the function get_total(). Consequently, I get an error that says:
Uncaught (in promise) TypeError: comp_1.get_total is not a function
at VotingPoll.get_winner (classes.ts:111)
at fillTable (end.ts:35)
at HTMLInputElement.<anonymous> (add_listeners.ts:25)
If anyones have any idea on how to do this, or if you have another approach, please help me. Thanks!

Unable to minify javascript class

I have created a JavaScript class. I'm getting an error when I try to minify the code using javascript-minifier. Can you help me to fix this issue?
My code:
class Test {
onCompleted = () => {};
onDismissed = () => {};
onError = () => {};
isProgress = false;
popup;
payment;
startPayment(payment) {
this.payment = payment;
this.isProgress = true;
this.popup = window.open('---');
var timer = setInterval(function () {
if (this.Test.popup.closed) {
clearInterval(timer);
if (this.Test.isProgress) {
this.Test.isProgress = false;
this.Test.onDismissed();
}
}
}, 500);
}
}
const Test = new Test();
window.addEventListener('beforeunload', function () {
if (Test.popup != null && !Test.popup.closed) {
Test.popup.close();
}
});
window.Test = Test;
Error message:
// Error : Unexpected token: operator (=)
// Line : 2
// Col : 18
The way you are creating the class seems to be wrong. In classes you can use functions like this: onCompleted() {}; and you can create variables in constructor. I also fixed an issue where you have Test defined twice, one as the class and one as variable. I renamed variable to TestInstance
Here would be a fixed example:
class Test {
constructor() {
this.isProgress = false;
this.popup;
this.payment;
}
onCompleted () {};
onDismissed () {};
onError () {};
startPayment(payment) {
this.payment = payment;
this.isProgress = true;
this.popup = window.open("---");
var timer = setInterval(function () {
if (this.Test.popup.closed) {
clearInterval(timer);
if (this.Test.isProgress) {
this.Test.isProgress = false;
this.Test.onDismissed();
}
}
}, 500);
}
}
const TestInstance = new Test();
window.addEventListener("beforeunload", function () {
if (TestInstance.popup != null && !TestInstance.popup.closed) {
TestInstance.popup.close();
}
});
window.Test = TestInstance;
A minified version:
class Test{constructor(){this.isProgress=!1,this.popup,this.payment}onCompleted(){}onDismissed(){}onError(){}startPayment(s){this.payment=s,this.isProgress=!0,this.popup=window.open("---");var t=setInterval(function(){this.Test.popup.closed&&(clearInterval(t),this.Test.isProgress&&(this.Test.isProgress=!1,this.Test.onDismissed()))},500)}}const TestInstance=new Test;window.addEventListener("beforeunload",function(){null==TestInstance.popup||TestInstance.popup.closed||TestInstance.popup.close()}),window.Test=TestInstance;

Cannot read property 'bind' of undefined, React.js

When binding this to my addTimes function I get an error stating: Cannot read property 'bind' of undefined.
I am building in ReactjJS and Webpack.
I recently had another issue recent which people suggested:
this.addTimes = this.addTimes.bind(this);
See: Cannot read property 'setState' of undefined ReactJS
class Settings extends React.Component {
constructor(props) {
super(props);
this.state = {
times: []
};
}
render(){
this.addTimes = this.addTimes.bind(this);
Array.prototype.remove = function() {
var what, a = arguments, L = a.length, ax;
while (L && this.length) {
what = a[--L];
while ((ax = this.indexOf(what)) !== -1) {
this.splice(ax, 1);
}
}
return this;
};
var currentTicked = [];
var times =[]
function addTimes(id){
var index = times.indexOf(id);
if (!times.includes(id)) {
$("input:checkbox[name=time]:checked").each(function(){
currentTicked.push($(this).val());
times = times.concat(currentTicked)
times = jQuery.unique(times);
currentTicked = [];
});
} else if(times.includes(id)){
times = times.remove(id);
}
console.log(times);
this.setState = {
thims: times
}
}
In order to be able to bind addTimes to this in the constructor, addTimes must be a method on your class, not just a function in the render method.
class Settings extends React.Component {
constructor(props) {
super(props);
this.state = {
times: []
};
this.addTimes = this.addTimes.bind(this);
}
addTimes(id) {
// ...
}
}
If you want to create addTimes in the render method, you could just bind this to the function there:
function addTimes(id) {
// ...
}.bind(this);
Or your could make it into an arrow function instead:
const addTimes = (id) => {
// ...
}

Redux doesn't behave correctly

I just learned a little of react-redux and stuck at such problems I cannot understand and fix at least 4 days long.
First of the problem stands and can be seen at inspectors console (I use Chrome).
I have event handler at <div> inside react component. It have to be called at onClick event but it triggers at each load or reload of site.
Second, stands somewhere near reducer's function. It says me in console (dev tools) that reducers received action 'TOGGLE_TILE' and returned undefined instead of object. Should notice that reducer successfully receives state, action properties and makes some operations inside but as result nothing normal returnes.
The code of my reducer, actions, main, container, presentation components and functions provide. Please answer expanded as you can, i want to understand whats wrong and not make this mistake inside code twice.
ALSO! I using redux-thunk middleware (to functional callbacks inside actions, you know).
Inside i have:
index.js - main component
const store = createStore(reducer, applyMiddleware(thunk));
ReactDOM.render(
<Provider store={store}>
<AppContainer />
</Provider>,
document.getElementById('root')
);
registerServiceWorker();
actions.js
export function toggle(id){
return{
type: 'TOGGLE_TILE',
id
};
}
export function toggleTile(id){
return dispatch => {
console.log('toggling');
dispatch(toggle(id));
};
}
tiles.js - Reducer
var i = 0;
function tiles(state = tilesContainer, action){
var openedTiles = [];
switch (action.type) {
case 'TOGGLE_TILE':
if(i < 2){
console.log('i: '+i);
state.map((value) => {
var newOpen;
if(!value.opened && action.id === value.id){
newOpen = Object.assign({}, value, {
opened: !value.opened
});
openedTiles.push(newOpen);
i++;
console.log(i, value.opened, newOpen, openedTiles);
}
return newOpen, i;
});
}else if(i === 2){
var curr, prev;
openedTiles.map((value) => {
if(!prev){
prev = value;
}else{
curr = value;
console.log("Prev and curr: "+prev, curr);
if(curr.name === prev.name){
var currRes = Object.assign({}, curr, {
disappeared: !curr.disappeared
});
var prevRes = Object.assign({}, prev, {
disappeared: !prev.disappeared
});
return {currRes, prevRes};
} else {
let currRes = Object.assign({}, curr, {
opened: !curr.opened
});
let prevRes = Object.assign({}, prev, {
opened: !prev.opened
})
return currRes, prevRes;
}
}
});
}else{
return state;
}
default:
return state;
}
console.log("tiles: "+state.forEach(value => console.log(value)));
}
const reducers = combineReducers({
tiles
});
export default reducers;
AppContainer.jsx
const mapStateToProps = (state) => {
return {
tiles: state.tiles
};
};
const mapDispatchToProps = (dispatch) => {
return {
toggle: id => {
// console.log(id);
dispatch(toggleTile(id));
}
};
};
class AppContainer extends Component {
constructor(props){
super(props);
}
componentDidMount(){
}
render() {
var prop = this.props;
console.log(prop);
return (
<div>
<AppView prop={prop} />
</div>
);
}
}
export default connect(mapStateToProps, mapDispatchToProps)(AppContainer);
AppView.js
class AppView extends React.Component {
constructor(props){
super(props);
this.state = {
tiles: this.props.prop.tiles,
};
this.showTiles = this.showTiles.bind(this);
this.defineRatio = this.defineRatio.bind(this);
this.toggleTile = this.toggleTile.bind(this);
}
componentDidMount(){
this.defineRatio();
}
componentWillMount(){
}
defineRatio(){
var imgClass;
let tile = document.querySelectorAll('img');
tile.forEach((value) => {
var imgSrc, imgW, imgH;
function defineImage(imgSrc){
var img = new Image();
img.src = imgSrc;
img.onload = function() {
return {
src:imgSrc,
width:this.width,
height:this.height};
};
return img;
}
var x = defineImage(value.src);
x.addEventListener('load',function(){
imgSrc = x.src;
imgW = x.width;
imgH = x.height;
// console.log(value.src, imgW, imgH);
var imgClass = (imgW / imgH > 1) ? 'wide' : 'tall';
value.classList += imgClass;
});
});
}
toggleTile(id){
this.props.prop.toggle(id);
}
showTiles(){
const boxElems = this.state.tiles.map((value, index) => {
var styles = {background: 'black'};
var tileState = value.opened ? '' : styles;
var imgState = value.opened ? 'opened ' : 'closed ';
var elem = <img key={value.id} src={value.src} alt="" className={imgState} />;
var boxElem = <div style={tileState} className="tile-box " onClick={this.toggleTile(value.id)} key={index}>{elem}</div>;
return boxElem;
});
return boxElems;
}
render(){
var tiles = this.showTiles();
return (
<div className="tiles-box">
<div className="tiles">
{tiles}
</div>
</div>
);
}
}
export default AppView;
First problem can be solved by replacing
onClick={this.toggleTile(value.id)}
with onClick={(e) => this.toggleTile(value.id)} First statement is just invoking this.toggleTile(value.id) immediately and setting the return value to OnClick event.
Regarding second you are not returning any thing from your reducer , hence state is undefined.
if(i < 2){
console.log('i: '+i);
state.map((value) => {
var newOpen;
if(!value.opened && action.id === value.id){
newOpen = Object.assign({}, value, {
opened: !value.opened
});
openedTiles.push(newOpen);
i++;
console.log(i, value.opened, newOpen, openedTiles);
}
return newOpen, i;
});
}
What is this return newOpen, i it should be return newOpen, also as this return is in a map function you have to return the mapped array as well
so use return state.map((value) => {
the problem that you have is that you are actually calling the function inside your div, thus it will get triggered each time you enter the view, so replace the following code on your showTiles()
var boxElem = <div style={tileState} className="tile-box " onClick={this.toggleTile(value.id)} key={index}>{elem}</div>;
to this:
var boxElem = <div style={tileState} className="tile-box " onClick={e => this.toggleTile(value.id)} key={index}>{elem}</div>;
and actually this should fix the error for the point 2.

Javascript object not recognizing function

I have a Javascript class defined as below:
function Node(init, parent) {
this.value = init;
this.children = [];
this.updateChildren(this.value);
}
Node.prototype.updateChildren = function(value) {
this.children.push(value);
};
When I run it.. i receive the error,
this.updateChildren() is not defined.
Any clue what I am missing here ?
Full code here :
'use strict';
var millionNumbers = [];
for (var i = 2; i< 1000000; i++) {
if (!millionNumbers[i]) {
millionNumbers[i] = new Node(i, null);
}
}
function Node(init, parent) {
this.value = init;
this.children = [];
if (parent) {
this.parent = parent;
}
var newValue;
if (isEven(this.value)) {
newValue = this.value/2;
} else {
newValue = (this.value * 3) + 1;
}
//whether newValue is 1 or something else, we still have add it to the children list
this.updateChildren(newValue);
if (millionNumbers[newValue]) {
var chainedNode = millionNumbers[newValue];
this.children.concat(chainedNode.children);
}
if (newValue === 1) {
this.endChain();
} else {
new Node(newValue, this);
}
}
Node.prototype.updateChildren = function(value) {
this.children.push(value);
if(this.parent) {
this.parent.updateChildren(value);
}
};
Node.prototype.endChain = function() {
if (!millionNumbers[this.value]) {
millionNumbers[this.value] = this;
this.parent = null;
}
};
function isEven(value) {
if (value % 2 === 0) {
return true;
} else {
return false;
}
}
The for loop instantiates Node objects before Node.prototype.updateChildren is set, so within the Node constructor, this.updateChildren is still undefined.
To fix the problem, just move the for loop to the end of the file.
Also: Best of luck with the Collatz conjecture!
think you are calling these classes without defining them first.
You can try this way:
function updateChildren(value) {
this.children.push(value);
};
function Node(init, parent) {
this.value = init;
this.children = [];
this.updateChildren(value);
}
Node.prototype.updateChildren(value);

Categories