I've noticed that classes generated with makeStyles and the use of hooks follow this nomenclature:
while the classes generated with withStyles and the use of HOC follow this one:
Is there a way to use makeStyles (I like to use hooks) but keep the nomenclature of withStyles? I'd like this because it's easier to analyze the html in the browser and pinpoint the class that generated each element.
The second (optional) argument to makeStyles is an object of options to control the behavior of makeStyles. One of the options is a name which is then used as a prefix for the class names. withStyles passes Component.displayName as the name option. You can specify whatever name you want in order to control the class name prefix, for instance in my example below the class name ends up being Hello-root-1.
import { makeStyles } from "#material-ui/core/styles";
const useStyles = makeStyles(
{
root: {
backgroundColor: "green"
}
},
{ name: "Hello" }
);
export default function App() {
const classes = useStyles();
return (
<div>
<h1 className={classes.root}>Hello CodeSandbox</h1>
</div>
);
}
Related
I want to define jsx like this:
<table style={{'--length': array.lenght}}>
<tbody>
<tr>{array}</tr>
</tbody>
</table>
and I use --length in CSS, I also have cells that have --count that shows count using CSS pseudo selector (using the counter hack).
but typescript throws error:
TS2326: Types of property 'style' are incompatible.
Type '{ '--length': number; }' is not assignable to type 'CSSProperties'.
Object literal may only specify known properties, and ''--length'' does not exist in type 'CSSProperties'.
is it possible to change type of style attribute to accept CSS variable (custom properties) or is there a way to force any on style object?
Like this:
function Component() {
const style = { "--my-css-var": 10 } as React.CSSProperties;
return <div style={style}>...</div>
}
Or without the extra style variable:
function Component() {
return <div style={{ "--my-css-var": 10 } as React.CSSProperties} />
}
If you go to the definition of CSSProperties, you'll see:
export interface CSSProperties extends CSS.Properties<string | number> {
/**
* The index signature was removed to enable closed typing for style
* using CSSType. You're able to use type assertion or module augmentation
* to add properties or an index signature of your own.
*
* For examples and more information, visit:
* https://github.com/frenic/csstype#what-should-i-do-when-i-get-type-errors
*/
}
That page gives examples of how to solve the type error by augmenting the definition of Properties in csstype or casting the property name to any.
You can add a type assertion to the variable. i.e. {['--css-variable' as any]: value }
<table style={{['--length' as any]: array.length}}>
<tbody>
<tr>{array}</tr>
</tbody>
</table>
Casting the style to any defeats the whole purpose of using TypeScript, so I recommend extending React.CSSProperties with your custom set of properties:
import React, {CSSProperties} from 'react';
export interface MyCustomCSS extends CSSProperties {
'--length': number;
}
By extending React.CSSProperties, you will keep TypeScript's property checking alive and you will be allowed to use your custom --length property.
Using MyCustomCSS would look like this:
const MyComponent: React.FC = (): JSX.Element => {
return (
<input
style={
{
'--length': 300,
} as MyCustomCSS
}
/>
);
};
you can simply put this module declaration merge using string templates at the top of the file or in any .d.ts file, then you will be able to use any CSS variable as long it starts '--' and that is string or number
import 'react';
declare module 'react' {
interface CSSProperties {
[key: `--${string}`]: string | number
}
}
for example
<div style={{ "--value": percentage }} />
import "react";
type CustomProp = { [key in `--${string}`]: string };
declare module "react" {
export interface CSSProperties extends CustomProp {}
}
put this in your global.d.ts file
try:
<table style={{['--length' as string]: array.lenght}}>
...
</table>
I would like to add a different approach by using document.body.style.setProperty, and maybe if your css variable will be affected by certain props you can put it in a useEffect like this:
useEffect(() => {
document.body.style.setProperty(
"--image-width-portrait",
`${windowSize.width - 20}px`
);
}, [windowSize])
Later inside your css file you can call it like this:
width: var(--image-width-portrait);
These are (well almost) all valid approaches to solve this, but there is another.
You could add the ref to your element and set the style where ever. I know that this would be quite possibly an improper use of useEffect but if you have something in useEffect that needs to happen on component mount then:
const tableRef = useRef<HTMLTableElement | null>(null)
useEffect(() => {
tableRef?.current?.style.setProperty('--length': array.lenght);
}, [])
...
<table ref={tableRef}>
<tbody>
<tr>{array}</tr>
</tbody>
</table>
This can also be used on any interaction and event
I'm creating a React.js project and I want to pull a string from Firebase that has HTML tags and render those tags. However, when I render the string as a string interpolation inside of a JSX element, the HTML tags simply print as text instead of actually taking effect.
Here is the code:
import React from 'react';
import styled from 'styled-components';
import { firestore } from '../../firebase/firebase.utils';
const name = firestore.collection('blog-categories').doc('8uVaHd22tT5oXSzpOOuj').get().then(doc =>
doc.get('name'));
class Economics extends React.Component {
constructor() {
super();
this.state = {
name: '',
image: '',
whyRead: ''
}
}
componentDidMount() {
firestore.collection('blog-categories').doc('8uVaHd22tT5oXSzpOOuj').get().then(doc => {
this.setState({ name: doc.get('name'), image: doc.get('image'), whyRead: doc.get('why-read')
});
});
}
render() {
return (
<div>
<h1>{ `${this.state.whyRead}` }</h1>
</div>
)
}
}
export default Economics;
When I run this code, the result is simply the following:
However, I want the HTML bold tags to actually take effect and create bold text. How would I do this?
dangerouslySetInnerHTML
dangerouslySetInnerHTML is React’s replacement for using innerHTML in
the browser DOM. In general, setting HTML from code is risky because
it’s easy to inadvertently expose your users to a cross-site scripting
(XSS) attack. So, you can set HTML directly from React, but you have
to type out dangerouslySetInnerHTML and pass an object with a __html
key, to remind yourself that it’s dangerous.
https://reactjs.org/docs/dom-elements.html#dangerouslysetinnerhtml
return <div dangerouslySetInnerHTML={{__html: this.state.whyRead}} />;
Having an assets folder with :
/assets/images/image1.png
/assets/svg/svg1.svg
How to include it in an HTML template (not in a CSS file) in order to have angular/webpack to automatically enable cache-busting on it (transforming automaticallt assets/images/image1.jpg to assets/images/image1-4d5678xc0v987654v.jpg?
The goal is to handle cache and refresh it soon ASAP when an existing file gets updated.
With webpack, I used to do a :
<img src="<%=require("./assets/img/image1.jpg")%>" />
The only solution I found with angular is requiring all my images in the .ts file but it's quite a pain to do :
const image1src = require(`../assets/images/image1.jpg`);
class Component {
image1 = image1src; // contains image1-4d5678xc0v987654v.jpg
}
// and in template : <img [src]="image2" />
Is there something simplier ?
ps: I don't want to handle a query paremeter or custom name myself
pps: I don't want to inject these files through CSS (and I know it works when files are getting injected by css)
ppps: using a PWA is not an option in my case
Thanks
I created a pipe for this so I don't need to create variables inside a component as you did.
import {Pipe, PipeTransform} from '#angular/core';
#Pipe({
name: 'imgURL'
})
export class ImgURLPipe implements PipeTransform {
transform(value: string): string {
return require('../../../images/' + value); // specify here a correct src to your folder with images
}
}
To make the require works inside components or pipes, add this to your typings:
declare var require: {
<T>(path: string): T;
(paths: string[], callback: (...modules: any[]) => void): void;
ensure: (
paths: string[],
callback: (require: <T>(path: string) => T) => void
) => void;
};
Inside a template, it looks like this:
<img [src]="'myImage.png' | imgURL">
Remember to add a declaration of the pipe to your module.
are you using angular-cli?
Check this article, it explains how to manage the assets with angular-cli: https://kimsereyblog.blogspot.com/2017/09/manage-assets-and-static-files-with.html
Other solution would be to use css, eg:
background: url('../assets/fonts/roboto-v15-latin-regular.svg')
I was wondering if there is any possibility to add some functions to the prototype of a class in Typescript.
My situation is as this:
I've got a file with a class, e.g. image.ts:
export class Image {
b64img: string;
}
This class is generated and so I can't add methods to it. I'm using this class in other generated classes, so creating a new class with extends Image is not possible for adding functions.
Is there any option that I can add a function to my class in a separated file so I could use it on all objects of the class Image?
Thanks
You can. You can extend it by defining an extension to the module it is defined in.
Create a file called image-extension.ts or something like that.
Now, if in that file you would import Image like this:
import { Image } from `image`;
declare module 'image' { // same name than in the import!
export interface Image {
newMethod: () => void;
}
}
Image.prototype.newMethod = function() {
console.log('new method');
}
Now, wherever you import this file, you can use that method:
import { Image } from 'image';
import 'image-extension'; // import just for side-effects
Of course, you can also add the declare module to a d.ts file, so it gets loaded automatically, and in another file add the true functions to the prototype, making sure that such a file gets loaded in your application
I am learning react native. i want to rewrite the following line using a plain javascript class.
module.exports = React.createClass({
to
export class Dashboard extends React.Component {
not sure if i am doing it right. in the original code, it just exports without giving a class name. can I do the same? or does it hurt if I give a name.
the full source code is there. the line i try to modify is line 19.
I depends on how you import the component. You are currently using named export so you need to import it by it's name - Dashboard:
export class Dashboard extends React.Component {
// and then import by name
import { Dashboard } from './myfile';
// or with require
var Dashboard = require('./myfile').Dashboard;
If you use default export you can name it however you like:
export default class Dashboard extends React.Component {
// and then import
import Dashboard from './myfile';
// or with custom name
import MyComponent from './myfile';
// or with require
var Dashboard = require('./myfile');