how to isolate a file's css from another file's css in react - html

We are currently working on a project where,
project structure demo:
whenever i use pdf.js and pdf.css in seperate project then it works perfectly.But when i put that pdf js and css inside this project ,then the css of the projects overriding the pdf.css
is there any way to use separate css files each component?
i have tried doing modules.css ,but i have to change the existing all css for that,
please provide some suggestion

Here is a reference to React's docs. Basically you need to name your file {file_name}.module.css, where the file extension needs to end with module.css
Then you can use like this, as shown on React example:
Class based component
import React, { Component } from 'react';
import styles from './Button.module.css'; // Import css modules stylesheet as styles
import './another-stylesheet.css'; // Import regular stylesheet
class Button extends Component {
render() {
// reference as a js object
return <button className={styles.error}>Error Button</button>;
}
}
Functional base component
import React, { Component } from 'react';
import styles from './Button.module.css'; // Import css modules stylesheet as styles
import './another-stylesheet.css'; // Import regular stylesheet
const Button = () => {
return <button className={styles.error}>Error Button</button>
}

Related

React - is the following true about how html tags' attribute values change when a component is reexecuted?

Can I verify my observation (based on the code below)?:
Class values of an element added in the html markup of a component don't neccessarily 'persist' - when the component is re-executed (perhaps as the result of a change in state), the class value from the last execution can disappear.
However, class values written via vanilla JS persist.
I'm always looking for best practices in code to avoid problems down the line. Is this code a reasonable way to add a class to a tag in React?
sandbox: https://codesandbox.io/s/purple-moon-epmmu?file=/src/styles.css:59-126
import "./styles.css";
import React, { useState, useEffect } from "react";
export default function App() {
let [color, setColor] = useState(false);
function updateColor() {
if (color) {
setColor("");
} else {
setColor("red");
}
}
useEffect(() => {
document.querySelector(`div`).classList.add(`green-text`);
}, []);
return (
<>
<div className={color ? "red" : null} onClick={updateColor}>
Click to add/remove red class
</div>
</>
);
}
.red {
background-color: red;
}
.green-text {
color: green;
}
I would highly recommend you to try out the classnames library to inject class attribute value dynamically. It's a very elegant library which helps avoid complicated code pertaining to css updates, when the codebase gets bigger.
I have tweaked your example, including some naming changes, removing unwanted code and added classnames. Also you can pass in any other class names from other components as such, and render it dynamically too. This is how you'd do it:
import "./styles.css";
import React, { useState, useEffect } from "react";
import classnames from "classnames"
export default function App(props) {
const [hasRed, setHasRed] = useState(false);
return (
<div className={classnames(
["green-text", props.otherClassNamesIfAny],
{
"red": hasRed,
}
)}
onClick={setHasRed(!hasRed)}
>
Click to add/remove red class
</div>
);
};

i18next/i18n Change Language not working with the whole website

I'm doing a react-typescript app where I need to be able to translate the site. I'm using the i18next library. In the main page the user can change the language using a button which runs this method.
changeLang(lang:string):any{
i18next.changeLanguage(lang).then(() => {
this.props.close();
i18next.options.lng = lang;
});
}
This works great for changing the language of the main page. However when I go to the next page it goes back to the original language. I can't seem to get the whole site running on a different language.
My index.tsx file
import React from 'react';
import ReactDOM from 'react-dom';
import './styles/index.css';
import App from './App';
import reportWebVitals from './reportWebVitals';
import Amplify from 'aws-amplify';
import awsmobile from "./aws-exports";
import * as enTranslations from "./locales/en"; /* This import refers to all of the texts in english */
import * as ptTranslations from "./locales/pt" /* This import refers to all of the texts in portuguese */
import {initReactI18next, I18nextProvider} from 'react-i18next'; /* Import needed for the use of the dictionary/translation */
import LanguageDetector from "i18next-browser-languagedetector"; /* Import needed for the use of the dictionary/translation */
import i18next from "i18next"; /* Import needed for the use of the dictionary/translation */
/* Configure Amplify on the client so that we can use it to interact with our backend services */
Amplify.configure(awsmobile);
/* Extract the translations */
const resources = {
en: {messages: enTranslations},
pt: {messages: ptTranslations}
};
/* Setting up the dictionary/translator */
const i18n = i18next.use(LanguageDetector).use(initReactI18next);
i18n.init({
react: {
wait: true,
},
resources: resources,
lng: 'pt', /* Main Language */
fallbackLng: 'en',
keySeparator: '.',
interpolation: {
escapeValue: false,
},
ns: ['messages'],
defaultNS: 'messages',
fallbackNS: [],
});
ReactDOM.render(
<I18nextProvider i18n={i18n}>
<App />
</I18nextProvider>,
document.getElementById('root')
);
reportWebVitals();
All the pages on my website have the following structure:
import { Component } from "react"
import { AuthProps } from "../../#types/auth" // Imports Auth props used to authenticate user
import { FontAwesomeIcon } from "#fortawesome/react-fontawesome" /* Import needed to be able to use the custom FontAwesome font */
import { faChevronLeft } from "#fortawesome/free-solid-svg-icons" /* Import needed to get the desired font elements */
import i18next from "i18next"; /* Import needed for the use of the dictionary/translation */
import { withTranslation } from 'react-i18next'; /* Import needed for the use of the dictionary/translation */
import '../styles/views/change-password-confirm.css';
/**
* Simple page that tells our user that his password has been changed
*/
class ChangePasswordConfirmation extends Component<AuthProps> {
render() {
return (
<div className="change-password-confirm-background">
<div className="change-password-confirm-main">
<div className="change-password-confirm-container">
{/* Button used to go back to the login page */}
<FontAwesomeIcon icon={faChevronLeft}></FontAwesomeIcon>
<h1>{i18next.t('ChangePasswordConfirm.catchphrase')}</h1>
<p>{i18next.t('ChangePasswordConfirm.secondaryText')}</p>
</div>
</div>
</div>
)
}
}
export default withTranslation()(ChangePasswordConfirmation)
As you can see I use i18next.t('my-key') to get the translations and I export every component/page with "withTranslation()". So I don't know why the whole website doesn't change language. Can anyone help me?
So I think the problem here is that you're importing i18next from the library on every page. What you're supposed to do is that you export the i18n you created in your index file and import it in every other file instead of importing a new i18next for every component you have there. Also try putting the language value of the whole website in some kinda global context incase you wanna change the language in other pages. I hope this was helpful!
I was running into the same issue with i18n.changeLanguage() method. So,I end up fixing this by getting the current language that the user is using in their browser,
const getUserLanguage = () => window.navigator.userLanguage || window.navigator.language;
window.navigator.language works for most of the modern browsers but to be on the safe side adding window.navigator.userLanguage
Now get the userlanguage by calling the getUserLangauge() method. And based on that change the language.
Something like this,
i18n.use(initReactI18next).init({
resources,
lng: `${userLanguage}`,
fallbackLng: 'en',
keySeparator: false,
interpolation: {
escapeValue: false,
},
});
But the downside is that we need to refresh the page when we switch the language. Note that, in production, it is just going to check the user's browser setting and render the specific language based on that. Users are not able to switch the language(the only way to switch is to change their language setting in their browser and refresh the page)
Just putting out there as someone can have the same issue, double check your imports of locales/lang/translations.json. I had a bad copy paste that make two of my language point to the same translation file, hence it was not translating anything

How to render component by adding the component using innerHTML?

I have a component A which only contain a div with an id and a buttons that renders a component inside the div using innterHTML document.getElementById('my-router-outlet').innerHTML = '<app-component-b-page></app-component-b-page>';. But this is not rendering I wonder why?.
I'm trying to avoid using ngIf to be a selector for which component should be rendered for performance reason. Also if I clear the innerHTML does the resources of that component will be cleared?
Okay so a few things here
innerHTML = '<app-component-b-page></app-component-b-page>' is never going to work, angular wont recognise the angular component tag from a innerHTML call
using *ngIf wont affect the performance of the page, so doing the following
<app-component-b-page *ngIf="value === true"></app-component-b-page>
is probably you best option here
If you really don't want to use *ngIf you can use #ViewChild and ComponentFactoryResolver
In your HTML
<!-- this is where your component will be rendered -->
<div #entry></div>
In your component
import { Component, OnInit, ViewChild, ViewContainerRef, ComponentFactoryResolver } from '#angular/core'
import { YourComponent } from ... // import the component you want to inject
// ...
export class ...
#ViewChild('entry', {read: ViewContainerRef, static: true }) entry: ViewContainerRef;
constructor(
private _resolver: ComponentFactoryResolver
) {}
showComponent() {
const factory = this._resolver.resolveComponentFactory(YourComponent);
// this will insert your component onto the page
const component = this.entry.createComponent(factory);
}
// and if you want to dynamically remove the created component you can do this
removeComponent() {
this.entry.clear();
}
You are adding the element to the dom directly and it's not rendered by Angular.
You should go for the *ngIf.

Angular 4 - MS Edge issue with ngIf not updating

I have an issue on Microsoft Edge where I have a page with a read only state for a form and a pencil edit button that just toggles a boolean in the component and that boolean is used on two divs to toggle which one is displayed using ngIf.
This works fine in chrome but not in IE. There are no errors in the console and even if I log the boolean as it is changed it logs the change.
I have seen several other posts with similar issues and it all seems to have to do with the click event going out of the angular zone for some reason.
With that being said I found out that I can do:
toggleEdit(event?): void {
if (event) {
event.preventDefault();
}
this.ngZone.run(() => {
this.isEditable = !this.isEditable;
});
}
That works on Edge and the divs toggle back and forth, BUT what I want to know is what is actually causing the click to go outside of the angular zone so that I can fix the actual issue.
Here is more of the actual code:
Personal Info Component
#Component({
selector: 'personal-info',
template: require('./personal_info.component.html'),
styles: [require('./personal_info.component.scss')]
})
export class PersonalInfoComponent implements OnInit {
isEditable: boolean = false;
ngOnInit: void {
...
}
toggleEdit(event?): void {
if (event) {
event.preventDefault();
}
this.isEditable = !this.isEditable;
}
}
Personal Info HTML
<div class='read-only container' *ngIf='!isEditable'>
<h2>Personal Information <a href (click)='toggleEdit($event)'><img class='pencil' src='/images/legal-purple.png'/></a></h2>
...
</div>
<div class='editable container' *ngIf='isEditable'>
...
</div>
Profile Component HTML
<h1>Your Profile</h1>
<personal-info></personal-info>
I am using angular at version 4.1.3 and zone at 0.8.10.
These are the current shims we are using:
import 'core-js/es6/symbol';
import 'core-js/es6/object';
import 'core-js/es6/function';
import 'core-js/es6/parse-int';
import 'core-js/es6/parse-float';
import 'core-js/es6/promise';
import 'core-js/es6/number';
import 'core-js/es6/math';
import 'core-js/es6/string';
import 'core-js/es6/date';
import 'core-js/es6/array';
import 'core-js/es6/regexp';
import 'core-js/es6/map';
import 'core-js/es6/set';
import 'core-js/es6/weak-map';
import 'core-js/es6/weak-set';
import 'core-js/es6/typed';
import 'core-js/es6/reflect';
import 'core-js/es7/reflect';
import 'zone.js/dist/zone';
import 'ts-helpers';

How to use a flat icon as link to change a route with react router

I'm using redux, react-router and Material-ui to make my App. I have a problem to show the details of an order. When the user click on a flat button, I want this button sends the user to a new url. I try to do this but it doesn't work.
import React, { Component, PropTypes } from 'react';
import { browserHistory } from 'react-router'
import FlatButton from 'material-ui/FlatButton';
const myButton = (props)=(
<FlatButton label="See details" onClick={()=>(browserHistory.push('/order/1'))}/>
)
export default myButton;
Try wrapping your <FlatButton/> component inside <Link to="/order/1">...</Link tags.
Note: You will have to import {Link} from 'react-router'