Let ReactJS mixins require an external module - javascript

I know we should avoid using mixins , but let's use it for this case.
I defined a few logging in/out functions as a mixins module and I require it in a number of components.
var loginStore = require('../../stores/LoginStore'); // this is the problem ?
var AuthMixins = {
statics: {
willTransitionTo(transition) {
console.log(loginStore.id);
if (!loginStore.isLoggedIn()) {
transition.redirect('login');
}
}
},
_getLoginState() {
return {
userLoggedIn: loginStore.isLoggedIn()
};
},
componentDidMount() {
this.changeListener = this._onChange;
loginStore.addChangeListener(this.changeListener);
},
_onChange() {
this.setState(this._getLoginState());
},
getInitialState() {
return {
userLoggedIn: this._getLoginState()
};
},
componentWillUnmount: function() {
loginStore.removeChangeListener(this.changeListener);
}
};
module.exports = AuthMixins;
LoginStore.js :
var AppDispatcher = require('../dispatchers/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var LoginStore = (function() {
var _cred = null,
_user = null,
id = Date.now();
var eventEmitter = new EventEmitter();
var _listenToLogin = function(action) {
if (action.actionType === 'LOGIN_USER') {
_cred = action.cred;
_user = action.user;
eventEmitter.emit('CHANGE');
} else if (action.actionType === 'LOGOUT_USER') {
_cred = null;
_user = null;
eventEmitter.emit('CHANGE');
}
};
AppDispatcher.register(_listenToLogin.bind(this));
var user = function() {
return _user;
};
var cred = function() {
return _cred;
};
var addChangeListener = function(cb) {
eventEmitter.on('CHANGE', cb);
};
var removeChangeListener = function(cb) {
eventEmitter.removeListener('CHANGE', cb);
};
var isLoggedIn = function() {
return (!!_user);
};
return ({
id: id,
user: user,
cred: cred,
isLoggedIn: isLoggedIn,
addChangeListener: addChangeListener,
removeChangeListener: removeChangeListener
});
})();
module.exports = LoginStore;
As you can see I want LoginStore to be Singleton , so when I access it from different parts of the code , it has the same state.
The following is how I use mixins :
About.js :
'use strict';
var React = require('react');
var AuthMixins = require('./mixins/LoginMixins');
var About = React.createClass({
displayName: 'About',
mixins: [AuthMixins],
getDefaultProps: function() {
return {
message: 'Default Prop for About page'
};
},
render: function() {
return (<div>
{this.props.message}
</div>);
}
});
module.exports = About;
Now, the problem is that every time About is loaded , a new instance of LoginStore is loaded. (not respecting this fact that we want it to be singleton) in return it shows that the user is not logged in.

Related

Cannot read property 'target' of undefined Function remove not working

I have an array that has 3 contacts. I want the same person's name to be deleted when I click on the delete button, but unfortunately I do not know where the problem is that it does not work.
I have two functions in this program, one removeContact to perform the delete operation
And I have a function called showrecords to get the content of the array and display the name and number of contacts with a dedicated delete button for each contact
In this program, I used the pattern builder pattern
Please guide me to the conclusion to solve the problem of not being deleted
Please click on the show Person button to test the program. Contacts will be displayed and click on the delete button. You will see that the delete operation is not performed.
function ElementBuilder(name) {
this.element = document.createElement(name);
this.appendSelector = function(selector) {
this.appendElement = document.querySelector(selector).appendChild(this.element);
return this
};
this.setAttribute = function(attribute, valueAttribute) {
this.element.setAttribute(attribute, valueAttribute)
return this;
};
this.addEventListener = function(event, fun) {
this.element.addEventListener(event, fun);
return this;
};
this.text = function(text) {
this.element.textContent = text;
return this;
};
this.build = function() {
return this.element;
};
}
const builder = {
create: function(name) {
return new ElementBuilder(name);
}
};
function PhoneBook() {
this.records = [{ name: "niloufar", phone: 1111 }, { name: "sara", phone: 2222 }, { name: "sara", phone: 3333 }];
// function remove
this.removeContact = function() {
const self = this
function removePerson(item) {
if (item.target.classList.contains('delbutton')) {
const remID = item.target.getAttribute('data-id');
self.records.splice(remID, 1);
}
}
return removePerson;
}
}
function Render(container) {
this.container = container;
const phoneBook = new PhoneBook();
const remove = phoneBook
.removeContact();
this.removeEntry = (item) => {
remove(item); //
this.showrecords();
}
this.init = function() {
const btn = builder
.create("button")
.text("show person")
.addEventListener("click", this.showrecords)
.appendSelector("div")
.build();
};
// Function: Read contacts from the array and display them
this.showrecords = () => {
const addBookId = document.getElementById('phone-book-container');
let index = 0;
addBookId.innerHTML = '';
const arry = phoneBook.records;
arry.forEach(elm => {
const nameContent = builder
.create('p')
.text(`${elm.name}`)
.appendSelector("div")
.build();
const phoneContent = builder
.create('p')
.text(`${elm.phone}`)
.appendSelector("div")
.build();
const anchor = builder
.create('a')
.addEventListener('click', this.removeEntry)
.setAttribute('href', '#')
.setAttribute('class', 'delbutton')
.setAttribute("id", "deleteButton")
.text("delete")
.setAttribute('date-id', `${index}`)
.appendSelector("div")
.build();
});
}
}
const phoneBookContainer = document.getElementById("phone-book-container");
const app = new Render(phoneBookContainer);
app.init();
<div id="phone-book-container"></div>
You have to pass the item (which is actually the event object) to your function:
function ElementBuilder(name) {
this.element = document.createElement(name);
this.appendSelector = function(selector) {
this.appendElement = document.querySelector(selector).appendChild(this.element);
return this
};
this.setAttribute = function(attribute, valueAttribute) {
this.element.setAttribute(attribute, valueAttribute)
return this;
};
this.addEventListener = function(event, fun) {
this.element.addEventListener(event, fun);
return this;
};
this.text = function(text) {
this.element.textContent = text;
return this;
};
this.build = function() {
return this.element;
};
}
const builder = {
create: function(name) {
return new ElementBuilder(name);
}
};
function PhoneBook() {
this.records = [{ name: "niloufar", phone: 1111 }, { name: "sara", phone: 2222 }, { name: "sara", phone: 3333 }];
// function remove
this.removeContact = function() {
const self = this
function removePerson(item) {
if (item.target.classList.contains('delbutton')) {
const remID = item.target.getAttribute('date-id');
self.records.splice(remID, 1);
}
}
return removePerson;
}
}
function Render(container) {
this.container = container;
const phoneBook = new PhoneBook();
const remove = phoneBook
.removeContact();
this.removeEntry = (item) => {
remove(item);
this.showrecords();
}
this.init = function() {
const btn = builder
.create("button")
.text("show person")
.addEventListener("click", this.showrecords)
.appendSelector("div")
.build();
};
// Function: Read contacts from the array and display them
this.showrecords = () => {
const addBookId = document.getElementById('phone-book-container');
addBookId.innerHTML = '';
const arry = phoneBook.records;
arry.forEach((elm, index) => {
const nameContent = builder
.create('p')
.text(`${elm.name}`)
.appendSelector("div")
.build();
const phoneContent = builder
.create('p')
.text(`${elm.phone}`)
.appendSelector("div")
.build();
const anchor = builder
.create('a')
.addEventListener('click', this.removeEntry)
.setAttribute('href', '#')
.setAttribute('class', 'delbutton')
.setAttribute("id", "deleteButton")
.text("delete")
.setAttribute('date-id', `${index}`)
.appendSelector("div")
.build();
});
}
}
const phoneBookContainer = document.getElementById("phone-book-container");
const app = new Render(phoneBookContainer);
app.init();
<div id="phone-book-container"></div>

module.exports with function

I have several JavaScript files that I create enums. for example:
source.enum.js
const enumUtils = require('../enum.utils');
const EmailAddressesSourceType = enumUtils.createEnum([
['DIRECTORY', 'directory'],
['FILE', 'file'],
['ARRAY', 'array']
]);
module.exports = { EmailAddressesSourceType };
The enum.utils.js is just a file that do the simple function of creating an enum from array:
class EnumUtils {
constructor() { }
// This method takes a map of elements and converts them to freeze objects (an enum-like object).
createEnum(mapItems) {
if (!mapItems || mapItems.length <= 0) {
throw new Error(`No array received: ${mapItems} (1000000)`);
}
const mapList = new Map([...mapItems]);
const symbolMap = {};
mapList.forEach((value, key) => { symbolMap[key] = value; });
return Object.freeze(symbolMap);
}
}
const enumUtils = new EnumUtils();
module.exports = enumUtils;
Now since I have 5-6 js files with enums, I want to avoid 'const enumUtils = require('../enum.utils');' in each of them, and do it all together in index.js file, something like this:
const { EmailAddressStatus, EmailAddressType, SendEmailStepName } = require('./files/emailAddress.enum');
const { Placeholder } = require('./files/placeholder.enum');
const { EmailAddressesSourceType } = require('./files/sources.enum');
const { Mode, Status, Method } = require('./files/system.enum');
const { StatusIcon, Color, ColorCode } = require('./files/text.enum');
const createEnum = (mapItems) => {
if (!mapItems || mapItems.length <= 0) {
throw new Error(`No array received: ${mapItems} (1000000)`);
}
const mapList = new Map([...mapItems]);
const symbolMap = {};
mapList.forEach((value, key) => { symbolMap[key] = value; });
return Object.freeze(symbolMap);
};
module.exports = {
createEnum(Color), createEnum(ColorCode), createEnum(EmailAddressStatus), createEnum(EmailAddressType), createEnum(EmailAddressesSourceType),
createEnum(Method), createEnum(Mode), createEnum(Placeholder), createEnum(SendEmailStepName), createEnum(Status), createEnum(StatusIcon)
};
But, there are compilation error in:
module.exports = {
createEnum(Color), createEnum(ColorCode), createEnum(EmailAddressStatus), createEnum(EmailAddressType), createEnum(EmailAddressesSourceType),
createEnum(Method), createEnum(Mode), createEnum(Placeholder), createEnum(SendEmailStepName), createEnum(Status), createEnum(StatusIcon)
};
My question is, there is a workaround so enable me to reduce the 'const enumUtils = require('../enum.utils');' in each file of the enums js file?
Thanks!
UPDATE 1
The error I'm getting is this:
The current status of the file (before I was trying to refactor) - It works OK:
index.js
const { EmailAddressStatus, EmailAddressType, SendEmailStepName } = require('./files/emailAddress.enum');
const { Placeholder } = require('./files/placeholder.enum');
const { EmailAddressesSourceType } = require('./files/sources.enum');
const { Mode, Status, Method } = require('./files/system.enum');
const { StatusIcon, Color, ColorCode } = require('./files/text.enum');
module.exports = {
Color, ColorCode, EmailAddressStatus, EmailAddressType, EmailAddressesSourceType,
Method, Mode, Placeholder, SendEmailStepName, Status, StatusIcon
};
This guy, guy-incognito, solved for me the issue. Now it works like a charm. Thanks man!
const { EmailAddressStatus, EmailAddressType, SendEmailStepName } = require('./files/emailAddress.enum');
const { Placeholder } = require('./files/placeholder.enum');
const { EmailAddressesSourceType } = require('./files/sources.enum');
const { Mode, Status, Method } = require('./files/system.enum');
const { StatusIcon, Color, ColorCode } = require('./files/text.enum');
const createEnum = (mapItems) => {
if (!mapItems || mapItems.length <= 0) {
throw new Error(`No array received: ${mapItems} (1000000)`);
}
const mapList = new Map([...mapItems]);
const symbolMap = {};
mapList.forEach((value, key) => { symbolMap[key] = value; });
return Object.freeze(symbolMap);
};
module.exports = {
Color: createEnum(Color),
ColorCode: createEnum(ColorCode),
EmailAddressStatus: createEnum(EmailAddressStatus),
EmailAddressType: createEnum(EmailAddressType),
EmailAddressesSourceType: createEnum(EmailAddressesSourceType),
Method: createEnum(Method),
Mode: createEnum(Mode),
Placeholder: createEnum(Placeholder),
SendEmailStepName: createEnum(SendEmailStepName),
Status: createEnum(Status),
StatusIcon: createEnum(StatusIcon)
};

Need to change socket.io class to singleton

What is the best way to make socket.io to a singleton? here i have three files i need to use socket.io method in user.mjs
socket.mjs
class socketBusiness extends baseBusiness {
//io = null;
//connectedUsers = {}
constructor(io) {
super(io);
this.io = io;
this.connectedUsers = {};
this.addUserRef= {};
this.bindEvents();
}
bindEvents() {
this.io.on("connection", this.onConnection);
this.io.use(this.onBeginConnection);
}
unBindEvents() {
this.io.off("connection", this.onConnection);
}
onConnection(socket) {
let _io = this.io;
let socketId = socket.id;
socket.on("disconnect", reason => {
});
socket.on("chat message", function(msg) {
});
}
addUserRef(userId, cstId) {
let arr = this.addUserRef[cstId] || [];
if (arr.indexOf(cstId) < 0) {
arr.push(cstId);
}
this.addUserRef[userId] = arr;
}
}
export default socketBusiness;
user.mjs
const socket = require("socket.mjs)
export async function addCst(req, res) {
socket.addUserRef(req.id,req.cstId)
}
How i can access the socket.io method ? any help will be highly appreciated
www.mjs
import socket from '../socket.mjs';
var server = createServer(app);
var io = new SocketServer(server, {})
var sb = new socketBusiness(io);
Export an instance:
export default new socketBusiness;
If you export a singleton, you can't pass io in the constructor. Move the initialization logic to a method:
constructor() { }
init(io) {
this.io = io;
this.bindEvents();
}
Then, initialize the singleton when you got the socket:
var io = new SocketServer(server, {})
socket.init(io);

Protractor - Failed: prop is not defined

Help please to find an error. I'm learning Protractor and try to create a simple test with Page Object.
//login_pageObject.js
let loginContainer = function() {
this.usernameInput = $("input.login-form-01");
this.passwordInput = $("input#login-form-02");
this.loginBtn = $("input.btn");
this.get = function() {
browser.get("https://www.cosmedicalsupplies.com/login.html");
};
this.setUsername = function(username) {
usernameInput.sendKeys(username);
};
this.setPassword = function(password) {
passwordInput.sendKeys(password);
};
this.clickOnLoginBtn = function() {
loginBtn.click();
};
};
module.exports = new loginContainer();
And
//login.js
let loginPage = require('../page_objects/login_pageObject.js');
describe('login_logout autotests', () => {
beforeEach(() => {
browser.ignoreSynchronization = true;
});
it("should sign in", () => {
loginPage.get();
loginPage.setUsername("test1");
loginPage.setPassword("test2");
loginPage.clickOnLoginBtn();
//expect.....
});
});
So, when I run this code, I have a "Failed: usernameInput is not defined" error. Where is mistake?
You need to refer to it as this.usernameInput.

Sinon async test: array is not filled in before push happens

I write test for AngularJS application in Sinon & Chai. I do $httpbackend request and I have a fake array of users - backendUsersResponse. It's available in my .spec.js but it's not filled in yet when I call the function openSettings and so my users are an empty array in my controller.
How & where can I tell my code to wait till array is filled in? How do you test async javascript stuff like this?
Thanks in advance!
Controller code:
export default class UserAccountsController {
constructor(UserModel, userSettingsDialog) {
this.UserModel = UserModel;
this.userSettingsDialog = userSettingsDialog;
this.users = [];
UserModel.query()
.then((users) => {
this.users = users;
});
}
openSettings(user) {
const userToUpdate = user || new this.UserModel();
this.userSettingsDialog.openDialog(userToUpdate)
.then((data) => {
const cmd = data.value;
if (cmd === 'saveSettings') {
const isNew = angular.isUndefined(userToUpdate.id);
userToUpdate.$save();
if (isNew) {
this.users.push(userToUpdate);
}
}
});
}
}
UserAccountsController.$inject = [ 'UserModel', 'userSettingsDialog'];
Test
import { expect } from 'chai';
import sinon from 'sinon/pkg/sinon';
describe('userAccounts Controller', () => {
'use strict';
beforeEach(angular.mock.module('myproject'));
let $httpBackend = null;
let $q = null;
let UserModel = null;
let userSettingsDialog = null;
beforeEach(inject(function(_$httpBackend_, _UserModel_, _$q_) {
$httpBackend = _$httpBackend_;
UserModel = _UserModel_;
$q = _$q_;
}));
describe('openSettings', () => {
let $controller;
let backendUsersResponse;
beforeEach(inject(function(_$controller_) {
userSettingsDialog = {
openDialog: sinon.stub(),
};
$controller = _$controller_;
backendUsersResponse = {
users: [
{
id: 1,
name: 'John',
role: 'admin',
},
{
id: 2,
name: 'Diego',
role: 'editor',
},
],
};
}));
it('should check if new user is pushed to an array', () => {
// arrange
const ctrl = $controller('UserAccountsController', {
userSettingsDialog: userSettingsDialog,
});
const user = new UserModel({
name: 'Lander',
});
const data = {
value: 'saveSettings',
};
$httpBackend.expectGET('api/users').respond(200, backendUsersResponse);
userSettingsDialog.openDialog.withArgs(user).returns($q.resolve(data));
$httpBackend.expectPOST('api/users').respond(200, user);
// act
ctrl.openSettings(user);
$httpBackend.flush();
// assert
expect(userSettingsDialog.openDialog).to.have.been.called;
expect(user.name).to.equal('Lander');
expect(ctrl.users).not.to.be.empty;
expect(ctrl.users.length).to.be(3); //<-- this one fails, array length is always 2, user is not added
});
});
});

Categories