Where should I put following line to get my component ready?
const classes = useStyles();
Try to use Material-UI MenuList component, but need to use in my existing MainPage code, what is slightly different from Material-UI code example.
constants are not supported at class level.
You have two options.
move the constants out of class and refer then.
Use static properties
This thread has some more information.
Declaring static constants in ES6 classes?
Could you try to call it inside render lifecycle ?
If i'm not wrong, u can't create const directly inside class, the order should be class > function > const or let var
Or you can try to put it inside constructor
Constructor(props) {
super(props)
this.classes = useStyles()
}
Or you can do it like seanplwong suggest
I think for class properties, the syntax should be something like
class Foo {
classes = useStyle();
}
Related
I am writing a node app in typescript. I have written a class decorator #myDecorator, and the purpose of #myDecorator is such that I need to keep track of all the classes to which it's applied.
My question: how do I make sure all of those decorated classes are loaded before making use of that behavior? Some example code will help to make this more concrete:
Declaration of the decorator in file myDecorator.ts:
type ConstructorType = { new (...args: any[]): any };
// keep track of decorated classes
const registeredClasses: Map<string, ConstructorType> = new Map();
// class decorator
export function myDecorator<T extends ConstructorType>(targetConstructor: T) {
// create the modified class
const newClass = class extends targetConstructor { /* ... */ }
// register the modified class
registeredClasses.set(targetConstructor.name, newClass);
// and return it
return newClass;
}
export function doSomethingWithMyDecoratedClasses() {
//... some behavior that relies on `registeredClasses`
}
Declaration of a decorated class in file someClass.ts
import {myDecorator} from 'myDecorator.ts'
#myDecorator
class SomeClass { /* ... */ }
Making use of doSomethingWithMyDecoratedClasses in anotherFile.ts:
import { doSomethingWithMyDecoratedClasses } from 'myDecorator.ts`
//...
doSomethingWithMyDecoratedClasses()
//...
The problem is that I need to make sure that SomeClass has been added to registeredClasses before I make this call to doSomethingWithMyDecoratedClasses. And, in fact, I've written a number of such classes in my app, and I need to make sure they are all registered.
My current best understanding is that I need to call import 'someClass.ts' in anotherFile.ts (and, in fact, import all files where decorated classes are declared), so really I need to import someClass1.ts, import someClass2.ts, ...
Is that the best/only approach? Is there a recommended pattern for doing so?
Most applications have an index file that is responsible for importing the top level things. If you import doSomethingWithMyDecoratedClasses there, you'll guarantee that everything else is imported first.
An alternative would be to not call it in the root level of a module, and instead wait for an event.
I want to use TypeScript in a NodeJS environment. Since I'm absolutely new to TypeScript I'm not sure how to extend classes properly with the NodeJS module system.
I want to extend my class Champion with GameObject.
GameObject.ts
///<reference path="../../typings/node/node.d.ts"/>
class GameObject {
id:number;
name:string;
}
module.exports = GameObject;
Champion.ts
///<reference path="../../typings/node/node.d.ts"/>
///<reference path="Image.ts"/>
///<reference path="GameObject.ts"/>
class Champion extends GameObject {
// ...
}
module.exports = Champion;
This throws no compilation error so far.
Now I want to create an instance of my Champion. This is what I've tried
// I tried referencing the Champion.ts which haven't changed anything
var Champion = require('../api/types/Champion');
var c = new Champion();
My Champion.js now throws the following error:
ReferenceError: GameObject is not defined
So I thought I need to require('GameObject') in Champion.ts which make my application running. But I get another error.
Either I reference and require my GameObject
///<reference path="GameObject.ts"/>
var GameObject = require('./GameObject');
class Champion extends GameObject {
Which gives me the error
Duplicate Identifier GameObject
Or I just require and get
Type any is not a constructor function type
TypeScript Version
$ tsc -v
message TS6029: Version 1.6.2
Instead of using module.exports = GameObject; with var/require use import/require
This will give you type safety on the import side. These are called file modules and documented here : https://basarat.gitbooks.io/typescript/content/docs/project/modules.html
I'm getting crazy with inheritance using typescript. I don't know why but it cannot resolve the class I want to inherit.
lib/classes/Message.class.ts
///<reference path='./def/lib.d.ts'/>
///<reference path='./def/node.d.ts'/>
export module SharedCommunication {
export class Message{
// Stuff
}
}
lib/classes/ValidatorMessage.class.ts
///<reference path='./def/lib.d.ts'/>
///<reference path='./def/node.d.ts'/>
///<reference path='Message.class.ts'/>
export module SharedCommunication {
export class ValidatorMessage extends Message{
private _errors;
}
}
Message cannot be resolved. I tried SharedCommunication.Message too but it's the same. I reference the class so I don't understand at all what's going on. Do you have any idea?
I tried without the module (two class without be in any module) but it's the same. I need to export the class (and the module if I use it) to get them from another node_module: typescript.api, which I use to load the class and use it in node.
lib/message.js
var Message = require('./classes/Message.class.ts');
module.exports = Message.SharedCommunication.Message;
What's the trick here? Because I have source code on the same project in a different folder working with inheritance, without module or export. Thanks.
ValidatorMessage.class.ts should look like this:
///<reference path='./def/lib.d.ts'/>
///<reference path='./def/node.d.ts'/>
import message = require('./Message.class');
export module SharedCommunication {
export class ValidatorMessage extends message.SharedCommunication.Message {
private _errors;
}
}
It's usually redundant to have a single export module at the top level of a file since the file itself constitutes a namespace anyway.
Bill mentioned this in your other question, but I'd again caution on using RequireTS if you're just starting out with TypeScript - it sounds pretty unmature and is likely to introduce a lot of confusion.
Take out the export from the mododule declaration:
module SharedCommunication
{
export class ValidatorMessage extends message.SharedCommunication.Message
{
private _errors;
}
}
What is best practice for importing modules in nodejs with typescript? I come from c# background so I want to do something like this
MyClass.ts
module MyNamespace {
export class MyClass {
}
}
app.ts
// something like using MyNamespace
new MyNamespace.MyClass();
or
MyClass.ts
export class MyClass {
}
app.ts
import MyClass = module("MyClass")
new MyClass();
I know I can do this and it will work, but then I have to think up for two names for each class
import MyClass2 = module("MyClass")
new MyClass2.MyClass();
Point is separating classes to multiple .ts files (preferably one file per class). So question is, how is this done?
You have two choices here:
If you insist on using CommonJS or AMD modules, then you will have to use external modules just the way you described it in your question. Whether or not you use a module to declare your own namespace is mostly a matter of taste. The only way to circumvent the issue of specifying two names is to create a variable that aliases the type:
mymodule.ts
export module MyNamespace {
export class MyClass {
}
}
app.ts
import ns = require('mymodule');
var myclass = new ns.MyNamespace.MyClass();
var myclassalias = ns.MyNamespace.MyClass;
var myclass2 = new myclassalias();
Your other option is to use internal modules which are mostly used to structure your code internally. Internal modules are brought into scope at compile time using reference paths.
mymodule.ts
module MyNamespace {
export class MyClass {
}
}
app.ts
///<reference path='mymodule.ts'/>
var myclass = new MyNamespace.MyClass();
I think you'll have to decide for yourself which of those two approaches is more appropriate.
You can import TypeScript modules into a node.js file using the typescript-require module, which was created for this specific purpose.
I would recommend against using the explicit module (or namespace) keyword, it's a vestigial remnant of an earlier time.* You generally don't need them because any typescript file with a top-level import or export is automatically a module. Your second myModule.ts example was good.
export class MyClass {
...
}
But when you import it to another typescript module, you'll want to use something like this:
import { MyClass } from './myModule';
var myInstance = new MyClass();
Personally, I don't like repetitiveness of line 1, but it is what the language calls for, so I've learned to accept it. I think the utility of this syntax isn't apparent unless you abandon the file-per-class pattern. You pick and choose what names to import from the module, so that no unintended namespace pollution occurs.
An alternative import syntax pulls in all names from the module, but you must qualify the names with the module when you use them. Therefore it is also name collision resistant.
import * as myModule from './myModule';
var myInstance = new myModule.MyClass();
There are exceptions to the general rule about not needing module / namespace keywords, but don't start by focusing on them. Think file == module.
I am using Yii framework in my web project. now, I have several modules and I want to use only one layout for all modules. I have used following codes for determining the layout for every controller/action in each module:
$this->layoutPath = Yii::getPathOfAlias('application.views.layouts');
$this->layout = '//layouts/myLayout';
Is there any other solution to do this by using same code in init() function of each module?
in other word, I have to write the above 2-line code in each action and i think it's not good and i want to reduce my number of lines of codes. for example as follows:
class StaffModule extends CWebModule
{
public $layout;
public $layoutPath;
public function init()
{
$this->layoutPath = Yii::getPathOfAlias('application.views.layouts');
$this->layout = '//layouts/myLayout';
$this->setImport(array(
'staff.models.*',
'staff.components.*',
));
}
}
but it doesn't work. Help me please.
Just use
$this->layout='//layouts/myLayout';
without
$this->layoutPath = Yii::getPathOfAlias('application.views.layouts');
because // mean you specific absolute path from root
The approach you are having in init function is in the right direction..I think the problem could be.. as you are defining layoutPath you shouldn't have //layouts..
$this->layoutPath = Yii::getPathOfAlias('application.views.layouts');
$this->layout = 'myLayout';
and you don't need these:
public $layout;
public $layoutPath;
I've answered similar question on
using common layout for several modules
The solution is set the layout on beforeControllerAction in your module.
It should work.