JavaScript es6 call static function from another class - javascript

Here is the class with the static function
import alt from '../alt';
import Parse from 'parse';
import { ElementTypes } from '../constants/ElementTypes';
class BoardActions {
static getDefaultElement(x, y) {
var Element = Parse.Object.extend("Element");
var element = new Element();
element.set("x", x);
element.set("y", y);
return element;
}
}
export default alt.createActions(BoardActions);
And this is the class who calls the static function const startElement = BoardActions.getDefaultElement(0, 3);
import alt from '../alt';
import Parse from 'parse';
import { ElementTypes } from '../constants/ElementTypes';
import BoardActions from './BoardActions';
class ProjectActions {
createNewProject(name) {
return (dispatch) => {
dispatch();
const Project = Parse.Object.extend("Project");
const project = new Project();
let projectObject = null;
project.set('name', name);
project.save().then((object) => {
projectObject = object;
const startElement = BoardActions.getDefaultElement(0, 3);
startElement.set('type', ElementTypes.StartType);
startElement.set('root', true);
startElement.set('projectId', object.id);
return startElement.save();
}).then((object) => {
this.newProjectCreated(projectObject);
}, (error) => {
this.parseError(error);
});
}
}
}
export default alt.createActions(ProjectActions);
I get this error:
ProjectActions.js:69 Uncaught TypeError: _BoardActions2.default.getDefaultElement is not a function
What's wrong?
Edit:
I use babel as transpiler.
"babel-core": "^6.5.1",
"babel-loader": "^6.2.2",
"babel-preset-es2015": "^6.5.0",
"babel-preset-react": "^6.5.0",
"babel-preset-react-hmre": "^1.1.0",
"babel-preset-survivejs-kanban": "^0.3.3",

EDITED (since you edited your question):
In the second file you are importing
import BoardActions from './BoardActions';
Which is importing the default from './BoardActions'.
Looking at the first file you are exporting the result of a function rather than the class itself.
export default alt.createActions(BoardActions);

Related

Assign object to a variable before exporting as module default warning

import axios from 'axios'
const baseUrl = 'http://localhost:3001/persons';
const getAll = () => {
return axios.get(baseUrl);
}
const create = (newObject) => {
return axios.post(baseUrl,newObject);
}
export default {
getAll:getAll,
create:create
}
Using axios to fetch data from server(in reactjs from json server), everything works fine but console shows this warning:
Line 13:1: Assign object to a variable before exporting as module default.
How to remove this warning??
You need to assign the object to a variable before exporting it as default.
const exportedObject = {
getAll,
create,
};
export default exportedObject;
You can also export the function individually to get rid of the warning:
import axios from 'axios';
const baseUrl = 'http://localhost:3001/persons';
export const getAll = () => { return axios.get(baseUrl); }
export const create = (newObject) => { return axios.post(baseUrl, newObject); }
You can remove this warning by just adding the comment "// eslint-disable-next-line" before export.
import axios from 'axios'
const baseUrl = 'http://localhost:3001/persons';
const getAll = () => {
return axios.get(baseUrl);
}
const create = (newObject) => {
return axios.post(baseUrl,newObject);
}
// eslint-disable-next-line
export default {
getAll:getAll,
create:create
}

TypeError: Cannot read property '0' of undefined resolveModel react-redux-form

Inside of the package.json file I have:
history: "^4.7.2",
react: "^16.4.1",
react-dom: "^16.4.1",
react-redux: "^5.0.7",
react-redux-form: "^1.16.9",
react-router-dom: "^4.3.1",
react-router-redux: "^4.0.8",
react-scripts: "1.1.4",
redux: "^3.5.2",
redux-form: "^7.3.0",
redux-logger: "^2.6.1"
The error I'm getting is
Cannot read property '0' of undefined;
resolveModel
node_modules/react-redux-form/lib/utils/resolve-model.js:32
function resolveModel(model, parentModel) {
if (parentModel) {
console.log('parentModel :', parentModel);
if (model[0] === '.' || model[0] === '[') { <-- It points to this line over here.
return '' + parentModel + model;
}
if (typeof model === 'function') {
return function (state) {
return model(state, parentModel);
};
}
}
return model;
}
function wrapWithModelResolver(WrappedComponent) {
var ResolvedModelWrapper = function (_PureComponent) {
_inherits(ResolvedModelWrapper, _PureComponent);
function ResolvedModelWrapper() {
_classCallCheck(this, ResolvedModelWrapper);
return _possibleConstructorReturn(this, (ResolvedModelWrapper.__proto__ || Object.getPrototypeOf(ResolvedModelWrapper)).apply(this, arguments));
}
_createClass(ResolvedModelWrapper, [{
key: 'render',
value: function render() {
var _context = this.context,
parentModel = _context.model,
localStore = _context.localStore;
var resolvedModel = resolveModel(this.props.model, parentModel); <------------------------ resolveModel gets called here.
return _react2.default.createElement(WrappedComponent, _extends({}, this.props, {
model: resolvedModel,
store: localStore || undefined
}));
}
}]);
return ResolvedModelWrapper;
}(_react.PureComponent);
ResolvedModelWrapper.displayName = 'Modeled(' + WrappedComponent.displayName + ')';
process.env.NODE_ENV !== "production" ? ResolvedModelWrapper.propTypes = {
model: _propTypes2.default.any
} : void 0;
ResolvedModelWrapper.contextTypes = {
model: _propTypes2.default.any,
localStore: _propTypes2.default.shape({
subscribe: _propTypes2.default.func,
dispatch: _propTypes2.default.func,
getState: _propTypes2.default.func
})
};
return ResolvedModelWrapper;
}
Inside of src/reducers/index.js
import { combineReducers } from 'redux';
import { createForms, formReducer } from 'react-redux-form';
import { routerReducer } from 'react-router-redux';
const SoundCloudState = {
input: ''
}
const reducer = combineReducers({
...createForms({
SoundCloud: SoundCloudState
}),
routing: routerReducer,
form: formReducer
});
export default reducer;
Inside of SoundCloudExp.js. In form component:
import React, { Component } from 'react';
import {querySC} from './actions/index';
import { connect } from 'react-redux';
import { Form, Control, actions, Errors } from 'react-redux-form';
class SoundCloudExp extends Component {
handleSubmit(query){
const {querySC, dispatch} = this.props;
let SCPromise = fetch('/', {
method: 'post',
body: query
})
.then((res) => res.json())
.then((res) => {
querySC(res);
});
dispatch(actions.submit('SoundCloud', SCPromise));
}
render(){
return (
<Form id="SC-search" model="SoundCloud" onSubmit={(query) => this.handleSubmit(query)}>
<div className='search-bar'>
<Control.text model=".input"
className='search'
placeholder='Search'/>
<Errors model=".input"
messages={{NoSearchResults: 'This query returned no results.'}}/>
</div>
<Control.button className='search-btn'>
Search
</Control.button>
</Form>
)
}
}
export default connect(null, {querySC})(SoundCloudExp);
What is peculiar is that when I include console.log statements inside of the resolveModel.js file, I get three different variations of the expected response. Why is that?
So basically I had to set a proper trigger for the NoSearchResults error, so I set that up in a sibling folder called services in a file called checkQueryValidity.js:
export default function checkQueryValidty(val){
return async (dispatch) => {
dispatch(actions.setPending('SoundCloud.input', true));
try {
let response = await querySC(val);
dispatch(actions.setValidity('SoundCloud.input', {
queries: response.queries
}));
}
catch(error){
dispatch(actions.setErrors('SoundCloud.input', {
NoSearchResults: error.message
}));
}
dispatch(actions.setPending('SoundCloud.input', false));
}
}
And in the file SoundCloudExp.jsx, I replaced SCPromise w/ checkQueryValidity(res) and replaced querySC(res); with dispatch(actions.submit('SoundCloud', checkQueryValidty(res)));

How to use deeplearn.js in a React component

I am currently working on creating a project with react and deeplearn.js, and have reached a roadblock when combining the two. In my react application I am importing this deeplearnjs library model which I am using to do classification. Unfortunately, when I try to call the predict() method I get the following error:
TypeError: _this.variables is undefined
For the following part of code:
SqueezeNet.prototype.predictWithActivation = function (input, activationName) {
var _this = this;
var _a = this.math.scope(function () {
var activation;
var preprocessedInput = _this.math.subtract(input.asType('float32'), _this.preprocessOffset);
When I use the generated Javascript in a normal HTML it works perfectly, so I am unsure why I am getting this error within react. I have a feeling it has to do with stricter React rules or Javascript versioning, but I am not sure.
Thanks!
UPDATE
The simplest way to reproduce this is the following:
Create a new React app with create-react-app
Run yarn add deeplearn and yarn add deeplearn-squeezenet
Modify App.js to the following:
import React, { Component } from 'react';
import {ENV, Array3D} from 'deeplearn';
import {SqueezeNet} from 'deeplearn-squeezenet';
class App extends Component {
constructor() {
super();
var net = new SqueezeNet(ENV.math);
net.load();
var img = new Image(227, 227);
img.src = 'boat.jpg';
img.onload = function () {
var pixels = Array3D.fromPixels(img)
var res = net.predict(pixels);
};
}
render() {
return (
<div></div>
);
}
}
export default App;
Download the following file into the public folder: https://raw.githubusercontent.com/PAIR-code/deeplearnjs/master/models/squeezenet/cat.jpg
Run yarn start
For reference I am using react 16.2.0
Your code is presumably failing because some of the method calls are asynchronous (.load() for example).
Here is how you would make your example work with React:
Create a new React app with create-react-app
Run yarn add deeplearn and yarn add deeplearn-squeezenet
Add cat.jpg to the public folder
Modify App.js as below
import React, { Component } from 'react';
import { ENV, Array3D } from 'deeplearn';
import { SqueezeNet } from 'deeplearn-squeezenet';
const math = ENV.math;
const squeezeNet = new SqueezeNet(math);
class App extends Component {
constructor() {
super();
this.state = {
statusText: 'Loading Squeezenet...'
}
}
buildSuggestions(obj){
return Object.keys(obj).map(
key => `${obj[key].toFixed(5)}: ${key}`
);
}
imageLoadHandler(e) {
const img = e.target;
squeezeNet.load()
.then(() => {
this.setState({ statusText: 'Predicting...' });
const pixels = Array3D.fromPixels(img);
const result = squeezeNet.predict(pixels);
this.setState({ statusText: '' });
squeezeNet.getTopKClasses(result, 5)
.then((obj) => {
this.setState({ statusText: this.buildSuggestions(obj) });
});
});
}
render() {
const text = Array.isArray(this.state.statusText)?
this.state.statusText :
[this.state.statusText];
return (
<div>
<img src="cat.jpg"
alt="cat"
onLoad={this.imageLoadHandler.bind(this)}
/>
<div id="result">
{ text.map(el => <div key={el}>{el}</div>) }
</div>
</div>
);
}
}
export default App;
Then run yarn start

ReactJS: Uncaught ReferenceError: [function] not defined, July 2017

Attempting to turn a JSON file into an array, then randomly selecting 5 items from it.
I think the issue is my render/return statement at the bottom of ImageContainer.js, but I'm a ReactJS n00b, so it could be anything.
Any help or advice is greatly appreciated.
Console Error
compiled.js:31562 Uncaught ReferenceError: selectImages is not defined
at ImageContainer.render (compiled.js:31562)
at compiled.js:20195
at measureLifeCyclePerf (compiled.js:19475)
at ReactCompositeComponentWrapper._renderValidatedComponentWithoutOwnerOrContext (compiled.js:20194)
at ReactCompositeComponentWrapper._renderValidatedComponent (compiled.js:20221)
at ReactCompositeComponentWrapper.performInitialMount (compiled.js:19761)
at ReactCompositeComponentWrapper.mountComponent (compiled.js:19657)
at Object.mountComponent (compiled.js:4009)
at ReactDOMComponent.mountChildren (compiled.js:24150)
at ReactDOMComponent._createInitialChildren (compiled.js:21126)
ImageContainer.js - pulls img info from a .JSON file, randomly selects 5 to render
import React from 'react';
import ReactDOM from 'react-dom';
import { Image } from './Image';
export class ImageContainer extends React.Component {
constructor(props) {
super(props);
this.numImages = 5;
this.state = {
data: []
};
}
componentDidMount() {
$.ajax({
url: '../app/data/namegame-data.json',
dataType: 'json',
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error('#GET Error', status, err.toString());
}.bind(this)
});
}
shuffleArray(array) {
let i = array.length - 1;
for (; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
const temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
selectImages({ data }) {
const shuffledImages = shuffleArray(images);
return (
shuffledImages.map((data, idx) => {
for (let i = 0; i < this.numImages; i++) {
if (this.state.data.length > 0) {
return <Image key={idx} name={data.name} src={data.src} />;
}
}
})
);
}
render() {
return {selectImages};
}
}
Image.js - just the image HTML
import React from 'react';
export class Image extends React.Component {
render() {
const key = this.props.id;
const name = this.props.name;
const src = this.props.src;
return (
<picture>
<img id="pic-template" className="pic" src="{src}" name="{name}" key="id" />
</picture>
);
}
}
[Main].js - most of the HTML is here, just including the import bits
import React from 'react';
import ReactDOM from 'react-dom';
import { ImageContainer } from './ImageContainer';
export default class NameGame extends React.Component {
render () {
return (
...
<div id="images-wrap">
<ImageContainer />
</div>
...
);
}
}
Dependencies
{
...
"dependencies": {
"json-loader": "^0.5.4",
"react": "^15.6.1",
"react-dom": "^15.6.1"
},
"devDependencies": {
"css-loader": "^0.28.4",
"extract-text-webpack-plugin": "^2.1.2",
"node-sass": "^4.5.3",
"sass-loader": "^6.0.6",
"style-loader": "^0.18.2",
"webpack": "^2.2.0",
"webpack-dev-server": "^2.5.0"
}
}
Here is the updated (mostly) working version of ImageContainer.js, which incorporates Danillo's changes and solves the array problem that followed. The issues were mainly related to missing "this." and "this.state."
ImageContainer.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Image } from './Image';
export class ImageContainer extends React.Component {
constructor(props) {
super(props);
this.numImages = 5;
this.state = {
data: []
};
}
componentWillMount() {
$.ajax({
url: './app/data/namegame-data.json',
dataType: 'json',
success: function(data) {
this.setState({data: data});
}.bind(this),
error: function(xhr, status, err) {
console.error('#GET Error', status, err.toString());
}.bind(this)
});
}
shuffleArray(array) {
let i = array.length - 1;
for (; i > 0; i--) {
const j = Math.floor(Math.random() * (i + 1));
const temp = array[i];
array[i] = array[j];
array[j] = temp;
}
return array;
}
selectImages() {
const shuffledImages = this.shuffleArray(this.state.data);
return (
shuffledImages.map((data, idx) => {
for (let i = 0; i < this.numImages; i++) {
return <Image key={idx} name={this.state.data.name} src={this.state.data.src} />;
}
})
);
}
render() {
return (
<div>
{this.selectImages()};
</div>
)
}
}
i think "this" is where it goes wrong ;):
selectImages is part of the ImageContainer class,
meaning the function is scoped within this Class, so it should be this.selectImages
In the render you call selectimages
render() {
return {this.selectImages()}; <-- its a function so u should call it as a function
}
Remember selectimage should return a react component, but if it will return a array of items that
react will render you should wrap it, you cannot pas multiple react elements to render
so you should something like
render() {
return (
<div> <-- give render 1 react component wrapping the multiple components
{this.selectImages()}; <-- its a function so u should call it as a function
</div>
)
}
selectImages({ data }) <-- where is it getting data from ? i don't think data is needed , only if u gonna pass { data: 'whatever' } to the function
shuffledImages.map((data, idx) => {
data will be the items from the shuffledImages array
})
const shuffledImages = shuffleArray(images); should be ->
const shuffledImages = this.shuffleArray(images);
about your other question
shuffleArray() {
(array) <-- u are mutating the data from the state, when u passed it to the function, u should only change state with setState.
use another shuffle function where u dont mutate the data ,use concat or es6 spread operator [ ...data ] etc .
read: "Correct modification of state arrays in ReactJS"
}
selectImages() {
const shuffledImages = this.shuffleArray(this.state.data); <-- u dont have to pass this.state.data, to the function ,it is accessable within shufflarray -> const shuffledImages = this.shuffleArray();
return (
shuffledImages.map((data, idx) => {
for (let i = 0; i < this.numImages; i++) {
return <Image key={idx} name={this.state.data.name} src={this.state.data.src} />;
}
})
);
}
if ur ajax call fails array is undefined. and u cannot call length on undefined. (thats what the error says)- about ur call
u need to tell ur ajax call what to do, is it a post or get?
add a 'type' (it should be type: 'get', )
or use the shorthand (i see u are using jquery)
$.getJSON('whateverjson file.json').done(function(response) {
console.log("Success");
}).fail(function() {
console.log("Error");
});
About the data ->
u should parse the json setstate({ data: JSON.parse(data) }) or setstate({ data: $.parseJSON(data) });
I must say using jquery, in combination with react, is not something i should recommend, jquery is mostly used for dom manipulation, react uses its virtual dom, and to include the whole jquery library for only the ajax requests is a waste.
try 'fetch' <==
PS look into https://facebook.github.io/react/docs/react-api.html (react docs)
Its also best to pass results of api calls to the component as props, but u will figure that out once u dive into the docs! i hope this helps u, good luck m8
i quickly changed ur code at 00:45 :D, but try something like this, explenation in my other answer. gl!
import React from 'react';
import ReactDOM from 'react-dom';
import { Image } from './Image';
export class ImageContainer extends React.Component {
constructor(props) {
super(props);
this.state = {
data: [],
numImages: 5
};
}
componentWillMount() {
$.ajax({
url: './app/data/namegame-data.json',
dataType: 'json',
type: 'get',
success: function(data) {
this.setState({data: JSON.parse(data) });
}.bind(this),
error: function(xhr, status, err) {
console.error('#GET Error', status, err.toString());
}.bind(this)
});
}
randomPickFromArray() {
// * as asked: " Attempting to turn a JSON file into an array, then randomly selecting 5 items from it. "
// lets not shuffle, and just random pick 5 items from array,
const { data, numImages } = this.state;
const arr = [];
for (let i = 0; i < numImages; i++) {
arr.push(data[Math.floor(Math.random() * data.length)]);
}
return arr;
}
selectImages() {
const shuffledImages = this.randomPickFromArray();
return shuffledImages.map((item, idx) => <Image key={idx} name={item.name} src={item.src} />);
}
render() {
return (
<div>
{this.selectImages()};
</div>
)
}
}

Hoist all expressions of a certain type to top scope using babel transform

At work, we have a custom solution for translations. The implementation is as follows:
In the smarty templates, get_string('unique_string_identifier', 'Default string') gets called in order to fetch a translated string.
The strings are stored in an SQL database.
If the string exists in the database, for the selected language (stored in session), the translated string is returned.
Else the default string is returned.
I'm currently in the process of rewriting parts of the application using React.js, and I'm implementing a javascript version of get_string (calling it getString).
The getString function lives in a global module called translate.
I need a way...
...to extract all the string identifiers and default strings from my files.
...for the react application to know which strings to request from the server (via api)
What I think would be a perfect solution is to create a babel transform that moves all getString calls to the top scope, leaving a variable as reference. This would allow me to solve both problems with relative ease.
import React from 'react'
import {getString} from 'translate'
export default class TestComponent extends React.Component {
render() {
const translatedString = getString('unique_string_identifier_1', 'Default string 1')
return <div>
{getString('unique_string_identifier_2', 'Default string 2')}
</div>
}
}
Would become something like:
import React from 'react'
import {getString} from 'translate'
const _getStringRef0 = getString('unique_string_identifier_1', 'Default string 1')
const _getStringRef1 = getString('unique_string_identifier_2', 'Default string 2')
export default class TestComponent extends React.Component {
render() {
const translatedString = _getStringRef0
return <div>
{_getStringRef1}
</div>
}
}
How would I go about doing this?
I've changed the requirements slightly, so...
import React from 'react'
import {getString, makeGetString} from 'translate'
const _ = makeGetString({
prefix: 'unique_prefix'
})
export default class TestComponent extends React.Component {
render() {
const translatedString = getString('unique_string_identifier_1', 'Default string 1 %s', dynamic1, dynamic2)
return <div>
{getString('unique_string_identifier_2', 'Default string 2')}
{_('string_identifier_3')}
</div>
}
}
becomes...
import React from 'react'
import {getString, makeGetString} from 'translate'
const _getString = getString('unique_string_identifier_1', 'Default string 1 %s');
const _getString2 = getString('unique_string_identifier_2', 'Default string 2');
const _ = makeGetString({
prefix: 'unique_prefix'
})
const _ref = _('string_identifier_3');
export default class TestComponent extends React.Component {
render() {
const translatedString = _getString(dynamic1, dynamic2)
return <div>
{_getString2()}
{_ref()}
</div>
}
}
This is actually what I have:
module.exports = function(babel) {
const {types: t} = babel
const origFnNames = [
'getString',
'makeGetString',
]
const getStringVisitor = {
CallExpression(path) {
const callee = path.get('callee')
if(callee && callee.node && this.fnMap[callee.node.name]) {
this.replacePaths.push(path)
}
}
}
const makeGetStringVisitor = {
VariableDeclaration(path) {
path.node.declarations.forEach((decl) => {
if(!(decl.init && decl.init.callee && !decl.parent)) {
return
}
const fnInfo = this.fnMap[decl.init.callee.name]
if(fnInfo && fnInfo.name === 'makeGetString') {
this.fnMap[decl.id.name] = {
name: decl.id.name,
path
}
}
})
}
}
return {
visitor: {
ImportDeclaration(path) {
if(path.node.source.value === 'translate') {
const fnMap = {}
path.node.specifiers.forEach((s) => {
if(origFnNames.indexOf(s.imported.name) !== -1) {
fnMap[s.local.name] = {
name: s.imported.name,
path
}
}
})
path.parentPath.traverse(makeGetStringVisitor, {fnMap})
const replacePaths = []
path.parentPath.traverse(getStringVisitor, {fnMap, replacePaths})
delete fnMap.makeGetString
Object.keys(fnMap).map((k) => {
const fnInfo = fnMap[k]
const paths = replacePaths.filter((p) => p.get('callee').node.name === fnInfo.name)
const expressions = paths.map((rPath) => {
const id = rPath.scope.generateUidIdentifierBasedOnNode(rPath.node)
const args = rPath.node.arguments
rPath.replaceWith(t.callExpression(id, args.slice(2)))
const expr = t.callExpression(t.identifier(fnInfo.name), args.slice(0, 2))
return t.variableDeclaration('const', [t.variableDeclarator(id, expr)])
})
fnInfo.path.insertAfter(expressions)
})
}
}
}
}
}

Categories