How to use a flat icon as link to change a route with react router - 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'

Related

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

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>
}

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

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';

What is ACTUALLY the right way to transition/redirect using React Router?

I'm in the process of learning React Router, and I can't seem to figure out what is currently the recommended way to redirect. I've read many articles and StackOverflow posts, but there is so much variety that I'm unsure of which one to implement for the current version of React Router.
What I'm trying to do is to redirect after an AJAX call using axios.
axios.post('/some-route')
.then(/*I want to redirect here*/)
Note: this code lives inside a function, inside a React.Component, that is called upon the submission of a form.
How do I accomplish this?
Please kindly let me know what details you need.
You can use browserHistory :
import { browserHistory } from "react-router";
browserHistory.push({
pathname: '/your/path'
});
This answer is for react-router-v4.
If you want to redirect from the same component (not from some action) and this component is rendered by some route then you can use history object passed in the props.
componentDidMount(){
if(this.state.some_param){
this.props.history.push("/some_location")
}
}
Best way is to create your own history object. You can use this history object in any action.
//history.js
import createHistory from 'history/createBrowserHistory'
export default createHistory()
then you can use this history in your router,
import history from "./history"
<Router history = {history}>
//other code
</Router>
now you can use this history object anywhere for redirect,
axios.post('/some-route')
.then(res=>{
history.push("/some_location")
})
const {Component} = React
const {render} = ReactDOM
const {Router, Link, Route, Switch, withRouter, Redirect} = ReactRouterDOM
const createHistory = History.createHashHistory
const myhistory = createHistory()
class App extends Component{
redirectToHome(){
myhistory.push("/home")
}
redirectToAbout(){
myhistory.push("/about")
}
render(){
return(
<div>
<Route path = "/home" component = {Home} />
<Route path = "/about" component = {About} />
<button onClick = {this.redirectToHome}>Redirect to home</button>
<button onClick = {this.redirectToAbout}>Redirect to about</button>
</div>
)
}
}
const Home = ()=>{
return(
<div>
Home
</div>
)
}
const About = ()=>{
return(
<div>About</div>
)
}
render(<Router history = {myhistory}><App/></Router>, document.getElementById('app'))
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.js"></script>
<script src="https://unpkg.com/react-router-dom#4.1.1/umd/react-router-dom.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/history/4.6.3/history.min.js"></script>
<div id="app"></div>
Starting from React Router v4, browserHistory is no longer exported from react-router.
You have two possibilities.
1) If your component is rendered via a route (is the component prop of a <Route> component, then you automatically get a few objects as props:
history
match
location
You can then use this.props.history.push("/some_location") in the context of the component
2) If your component is not related to a specific route, you can get the same props by using the withRouter high order component, which is part of react-router
import { withRouter } from "react-router-dom";
const Component = ( { history, location, match } ) => (
// your component code
);
export default withRouter(Component);