I am trying to set up the most basic app in Flux-React. Its sole goal to is fire an Action, which gets sent through the Dispatcher to a Store that has registered with the Dispatcher. The store the logs the payload to Console.
Everything besides the Store is working well, but as soon as it hits AppDispatcher.register, Flux throws the following error:
Uncaught TypeError: Cannot set property 'ID_1' of undefined
Here is the code of the file causing the error, but I've put up the entire project at https://github.com/bengrunfeld/react-flux-dispatcher-error, and you can find the offending file in src/js/stores/AppStores.js
var AppDispatcher = require('../dispatcher/AppDispatcher');
var EventEmitter = require('events').EventEmitter;
var AppConstants = require('../constants/AppConstants');
var assign = require('object-assign');
var CHANGE_EVENT = 'change';
var AppStore = assign({}, EventEmitter.prototype, {
emitChange: function() {
this.emit(CHANGE_EVENT);
}
});
AppDispatcher.register(function(payload){
console.log(payload);
return true;
})
module.exports = AppStore;
Because of the drought of documentation of biblical proportions for Facebook Flux, I didn't know that I was using code from previous versions.
In AppDispatcher.js, you need to define AppDispatcher in the following way using the new keyword:
var Dispatcher = require('flux').Dispatcher;
var assign = require('object-assign');
var AppDispatcher = assign(new Dispatcher(), {
handleViewAction: function(action) {
this.dispatch({
source: 'VIEW_ACTION',
action: action
});
}
});
module.exports = AppDispatcher;
Here is a link to a repository with the working code: https://github.com/bengrunfeld/react-flux-simple-app
Related
I have a readable store in Svelte that looks like this:
const state = {};
export const channels = readable(state, set => {
let st = state;
let socket = new WebSocket("ws://127.0.0.1:5999");
socket.onmessage = function (event) {
var datastr = event.data.split(':');
st[datastr[0]].value = datastr[1];
st[datastr[0]].timestamp = Date.now();
set(st)
};
return () => {
socket.close()
}
});
When I import it to my Svelte App works. But if I put that App.svelte as my index.svelte running on Sapper, it doesnt work at first. It says error 500 websocket is not defined. Once I reload the page in the browser start to work...
I have try to parse a function that creates the store instead:
export const getChannel = () => {
// here my store
return {...store}
}
and then creating the store inside a onMount() like this:
onMount( ()=> {
const channel = getChannel();
});
But doesnt seem to do the trick... What do I miss?
Note: If a just replace the store by a simple writable, and create the websocket onMount(), it works without any problem. I just only wanted to put all the communication inside the store as a readable...
In Sapper, code in components (or imported into components) is executed in Node during server-side rendering unless it's put inside onMount (which doesn't run on the server, because there's no 'mounting' happening) or an if (process.browser) {...} block, or something equivalent.
That includes things like references to $channels causing channels.subscribe(...) to be called during initialisation.
Since there's no WebSocket global in Node, creating that subscription will fail. The simplest workaround is probably a simple feature check:
const state = {};
export const channels = readable(state, (set) => {
if (typeof WebSocket === 'undefined') return;
let st = state;
let socket = new WebSocket("ws://127.0.0.1:5999");
socket.onmessage = function (event) {
var datastr = event.data.split(":");
st[datastr[0]].value = datastr[1];
st[datastr[0]].timestamp = Date.now();
set(st);
};
return () => {
socket.close();
};
});
function FriendlyChat() {
// statements
}
FriendlyChat.protoype.somemethod = function() {
// statements
};
FriendlyChat.protoype.somemethod2 = function() {
//statements
};
window.onload = function() {
window.friendlyChat = new FriendlyChat();
};
So i noticed the above structure for js while working on a google codelab.
And I have two ques.
in normal objects you have to call the function i.e Object.somemethod()
How does this structure call the methods assigned to it.
From my limited understanding, Firendlychat.protoype.the method treats the
function as an object and the methods are passed to the new object created on
window.onload.Via
inheritance, The object created i.e friendlychat has all these methods.
Yet none of the methods are called in any way. How does this work?
Is there any advantage to structuring your code in this way other than
readability
Note :
Main function
function FriendlyChat() {
this.checkSetup();
// Shortcuts to DOM Elements.
this.messageList = document.getElementById('messages');
this.messageForm = document.getElementById('message-form');
// Saves message on form submit.
this.messageForm.addEventListener('submit', this.saveMessage.bind(this));
this.signOutButton.addEventListener('click', this.signOut.bind(this));
this.signInButton.addEventListener('click', this.signIn.bind(this));
// Toggle for the button.
var buttonTogglingHandler = this.toggleButton.bind(this);
this.messageInput.addEventListener('keyup', buttonTogglingHandler);
this.messageInput.addEventListener('change', buttonTogglingHandler);
// Events for image upload.
this.submitImageButton.addEventListener('click', function(e) {
e.preventDefault();
this.mediaCapture.click();
}.bind(this));
this.mediaCapture.addEventListener('change',
this.saveImageMessage.bind(this));
this.initFirebase();
}
//the methods are setup here
// Sets up shortcuts to Firebase features and initiate firebase auth.
FriendlyChat.prototype.initFirebase = function() {
this.auth = firebase.auth();
this.database = firebase.database();
this.storage = firebase.storage();
// Initiates Firebase auth and listen to auth state changes.
this.auth.onAuthStateChanged(this.onAuthStateChanged.bind(this));
};
// Saves a new message on the Firebase DB.
FriendlyChat.prototype.saveMessage = function(e) {
e.preventDefault();
}
};
FriendlyChat.prototype.setImageUrl = function(imageUri, imgElement) {
imgElement.src = imageUri;
};
// Saves a new message containing an image URI in Firebase.
// This first saves the image in Firebase storage.
FriendlyChat.prototype.saveImageMessage = function(event) {
event.preventDefault();
var file = event.target.files[0];
// Clear the selection in the file picker input.
this.imageForm.reset();
// Check if the file is an image.
if (!file.type.match('image.*')) {
var data = {
message: 'You can only share images',
timeout: 2000
};
this.signInSnackbar.MaterialSnackbar.showSnackbar(data);
return;
}
// Check if the user is signed-in
if (this.checkSignedInWithMessage()) {
// TODO(DEVELOPER): Upload image to Firebase storage and add message.
}
};
// Signs-in Friendly Chat.
FriendlyChat.prototype.signIn = function() {
var provider = new firebase.auth.GoogleAuthProvider();
this.auth.signInWithRedirect(provider);
};
// Signs-out of Friendly Chat.
FriendlyChat.prototype.signOut = function() {
this.auth.signOut();
};
One of the advantages I've seen when using prototype inheritance was that you can control all instances of an object. For ex:
function FriendlyChat() {
this.chatIsActive = true;
}
FriendlyChat.prototype.deactivateChat = function(...rooms) {
for (chatRoom of rooms) {
chatRoom.chatIsActive = false;
}
};
var chat1 = new FriendlyChat();
var chat2 = new FriendlyChat();
var chatController = new FriendlyChat();
chatController.deactivateChat(chat1, chat2)
console.log(chat1.chatIsActive)
In ES6, however, you can do it:
class FriendlyChat {
constructor() {
this.chatIsActive = true;
}
static deactivateChat(...rooms) {
for (let chatRoom of rooms) {
chatRoom.chatIsActive = false;
}
}
}
var chat1 = new FriendlyChat();
var chat2 = new FriendlyChat();
FriendlyChat.deactivateChat(chat1, chat2)
console.log(chat1.chatIsActive)
And the another advantage of using prototype is that you can save memory spaces when you make an object from new keyword. For instance, the code in ES5 above, you can see chat1 and chat2 I've made by using new. Then chat1 and chat2 will be able to access deactivateChat() method which is in a sharing-space. It's because of the concept, called prototype-chaining.
And the next ES6 version is just a syntactic sugar - under the hood it does the same as ES5 version
I post this as a reference to others who have been faced with this dilemma.
First of all, ONe of the core issues for me was migrating from java, I seemed to be familiar territory but things work a bit different in js.I strongly recommend these links:
Objects in Detail
js Prototype
So the key to why this method works is due to the
window.friendlyapp =new friendlychat()
Now normally in most languages you have an object
obj() {
attr : value
method: function() {}
}
And then to use the method you do
var child = new obj();
child.method();
but in this method the var is made an instance of the window object and thats why none of the methods of the app need to be explicitly called.
I'm learning nodejs now and Im wondering how can I reference to the object created in a other file
for example:
I have a file with my class user.js which I'm exporting
module.exports = class Username {
constructor(name, lastProjects) {
this.current.name = name;
this.current.lastProjects = lastProjects;
}
};
name.handler.js I can not export it this to oder files
const Alexa = require('alexa-sdk');
const User = require('../models/user.model');
module.exports = Alexa.CreateStateHandler(StatesConst.NAME, {
'NewSession': function () {
this.emit('NewSession'); // Uses the handler in newSessionHandlers
},
'MyNameIsIntent': function() {
var user = new User.Username("Anna", ["project1", "project2"]);
this.emit(':ask', "Hi "+User.Username.name);
}
}
user.handler.js I tottaly dont know how can I write a reference to my new created object Username
const Alexa = require('alexa-sdk');
const User = require('../models/user.model');
module.exports = Alexa.CreateStateHandler(StatesConst.NEWSTATE, {
'NewSession': function () {
this.emit('NewSession'); // Uses the handler in newSessionHandlers
},
'MyUserIntent': function() {
this.emit(':ask', "My username is "+User.Username.name);
}
}
How can I reference to new user object in other files in my programm ? I want that everytime my user starts a program I will get a new user object and I could reference and change attributes in every other file. I would be very appreciate for a help :)
module.exports = Username;
const Alexa = require('alexa-sdk'); // ok?
const User = // in linux, to go 1 dir up is just '.'
console.log(require('../models/user.model'))
see if you get a message = '[Function: Username]'".
If not you will see a message telling you something. Maybe no found file.
Since you are exporting Username by assigning it to module.exports, you need to use it as new User in your handlers. For example, name.handler.js would become:
const Alexa = require('alexa-sdk');
const User = require('../models/user.model');
module.exports = Alexa.CreateStateHandler(StatesConst.NAME, {
'NewSession': function () {
this.emit('NewSession'); // Uses the handler in newSessionHandlers
},
'MyNameIsIntent': function() {
var user = new User("Anna", ["project1", "project2"]);
this.emit(':ask', "Hi "+user.name);
}
}
Note that in the this.emit line, you should use the instance of User, not the class itself. (so user instead of User).
Moreover, in your user.handler.js file, you don't instantiate any User. You will get a Cannot read property 'name' of undefined
Finally if your Username class is in user.js, your require statement should look like require('../models/user'), not require('../models/user-model')
I am trying to create two node.js files. I am using event emitter module. When ever i try to search through the data i want to emit an event so that event is raised before my data is returned from the array of objects.
// event emitter file:
var EventEmitter = require('events').EventEmitter;
var inherits = require('util').inherits;
var _ = require('underscore');
// Custom class
function EmployeeEmitter(args) {
this.data = args;
EventEmitter.call(this);
}
inherits(EmployeeEmitter, EventEmitter);
EmployeeEmitter.prototype.lookupByLastName = function (name) {
this.emit('lookupByLastName',name);
if( _.where(data, {lastName:name}))
{
return _.where(data, {lastName:name})
}
else{
return;
}
};
module.exports.EmployeeEmitter = EmployeeEmitter;
Now this is my event emitter which i want to fire lookupbylastName when the user searches through the data. For testing it i have created another file where i am using event.on method.Unfortunately its' not running it gives me error i dont know wats going wrong.
//Test file:
var colors = require('colors');
var EmployeeEmitter = require('./employeeEmitter').EmployeeEmitter;
// Usage
var data = [
{id:1, firstName:'John',lastName:'Smith'},
{id:2, firstName:'Jane',lastName:'Smith'},
{id:3, firstName:'John',lastName:'Doe'}
];
var employees = new EmployeeEmitter(data);
employees.on('lookupByLastName', function (args) {
});
console.log("\nLookup by last name (Smith)".red);
console.log(employees.lookupByLastName('Smith'));
I'm new to react/flux architecture, and I'm missing something...I think. I have two Stores, SubjectsStore.js and WorkDoneStore.js with an AppActions which does the dispatch (code snippets all below). I'm under the impression that any Store that registers with the AppDispatcher will get notice of the event, and it is incumbent on each store to handle the proper action types. There doesn't seem to be any other way of controlling which Store gets called. In my case, I've gotten as far as getting one the SubjectStores registration to be called, but my WorkDoneStore is not getting called. What am I overlooking / doing wrong.
AppActions.js
import AppDispatcher from './AppDispatcher.js';
import WorkDoneConstants from '../constants/WorkDoneConstants.js';
import SubjectConstants from '../constants/SubjectConstants.js';
var AppActions = {
addWorkDoneItem:function(item){
console.log("In app actions addWorkDone");
console.log(WorkDoneConstants.WORKDONE_INSERT);
AppDispatcher.dispatch({
actionType:WorkDoneConstants.WORKDONE_INSERT,
item:item
})
}
}
module.exports = AppActions;
SubjectsStore.js
var AppDispatcher = require('../dispatcher/AppDispatcher');
var SubjectConstants = require('../constants/SubjectConstants');
var EventEmitter = require('events').EventEmitter;
...
AppDispatcher.register(function(action) {
var text;
console.log("why am I in the subjectStore?");
console.log(action.actionType);
console.log(action.item);
switch(action.actionType) {
case SubjectConstants.SUBJECT_CREATE:
text = action.text.trim();
...
WorkDoneStore.js
...
AppDispatcher.register(function(action) {
var text;
console.log("In WorkDoneStore");
console.log(action);
switch(action.actionType) {
case WorkDoneConstants.WORKDONE_INSERT:
item = action.item;
if (item.subject !== '') {
create(item);
WorkDoneStore.emitChange();
}
break;
...
My component
...
handleSubmit: function(e){
e.preventDefault();
var item = {
subject:this.state.subject,
workDone:this.state.workDone,
minutes:this.state.totalMinutes,
startStop:this.state.startStop,
};
console.log("before AppActions.");
AppActions.addWorkDoneItem(item);
},
...
In looking through my Webpack output I noticed that the WorkDoneStore.js wasn't getting included. By forcing it to be included via a call to it, it's now working.