How to fix error override CSS when change component in ReactJS - javascript

Login.js
import React from 'react'
export default class Login extends React.Component {
componentWillMount(){
import ('./styles/login_page.css');
}
....
<Link to="/register">Create account</Link>
}
Register.js
import React from 'react''
export default class Register extends React.Component {
componentWillMount(){
import ('./styles/register_page.css');
}
....
<Link to="/login">Login Now</Link>
}
App.js
import React from 'react'
import ReactDOM from 'react-dom'
import { Route, Switch, BrowserRouter } from 'react-router-dom'
import Login from './Login'
import Register from './Register'
import PageNotFound from './PageNotFound'
ReactDOM.render(
<BrowserRouter>
<Switch>
<Route exact path='/login' component={Login }/>
<Route exact path='/' component={Home} />
<Route exact path='/register' component={Register }/>
<Route component={PageNotFound} />
</Switch>
</BrowserRouter>,
document.getElementById('root'));
After rendering, I click Login then click Create account and click again Login, login component's CSS is overrided by register component's CSS and home page is same. I want when going to any component, component's CSS is loading. Is there way to fix?

This is typically resolved by using descendant combinator in CSS. You need to set a distinct class in the root element of each component, and declare all other CSS styles by writing their selectors as descendants of that class.
Login.js
import React from 'react'
export default class Login extends React.Component {
componentWillMount(){
import ('./styles/login_page.css');
}
....
<Link class="login-component" to="/register">Create account</Link>
}
login_page.css
.login-component .item1 { ... }
.login-component .item2 { ... }
Register.js
import React from 'react''
export default class Register extends React.Component {
componentWillMount(){
import ('./styles/register_page.css');
}
....
<Link class="register-component" to="/login">Login Now</Link>
}
register_page.css
.register-component .item1 { ... }
.register-component .item2 { ... }
So even if both components have elements matching .item1 and .item2, they will select the correct rule due to the descendant combinator. This might be a bit verbose with raw CSS, but if you're using any preprocessor it should be pretty simple.
Else, you might just want to make the selectors distinct somehow.

I also faced the same challenge while using different css modules within the same app, I guess the problem is while the compiler is building the css, since all the css are compiled into a single file you might want differentiate them by giving them diffrent main class name.
The solution in that case is to nest your css styles in the base class if your using sass
.loginpageContainer {
.input{ //custom css
}}
.registerPageContainer{
.input{
// custom css
}}
Same wise if your using pure css just use the main class
.loginContainer .login .input{
//custom css
}
.registerContainer .login .input{
//custom css
}

Related

Add a Footer and Navigation to React app in the App.js file, including react routing?

I am trying to add a Footer to my App.js. I have already added the Navigation to the App.js file. I am wanting to add the Footer to every page instead of adding it onto the bottom of every page I make.
App.js file
import React from "react";
import { BrowserRouter as Router, Route, Switch } from "react-router-dom";
import "./App.css";
import DocumentTitle from "react-document-title";
import Home from "./pages/Home";
import NoMatch from "./components/NoMatch";
import Landing from "./components/Landing";
import Navigation from "./components/Navigation";
import Footer from "./components/Footer";
function App() {
return (
<DocumentTitle title="Page Title">
<Router>
<div>
<Navigation />
<Switch>
<Route exact path="/home" component={Home} />
<Route exact path="/" component={Landing} />
<Route component={NoMatch} />
</Switch>
{/* This Footer placement doesn't work */}
<Footer />
</div>
</Router>
</DocumentTitle>
);
}`
Every time I place the <Footer /> somewhere.. the DOM crashes. Here is an example of what I am receiving...
Error
×
Error: Element type is invalid: expected a string (for built-in components) or a class/function (for composite components) but got: object. You likely forgot to export your component from the file it's defined in, or you might have mixed up default and named imports.
Check the render method of App.
Attached is a Footer.js and Navigation.js file for ease..
Footer.js
import React from "react";
function Footer() {
return (
<div>
<footer>Footer</footer>
</div>
);
}
export default Footer;
Navigation.js
import React from "react";
function Navigation() {
return (
<div>
<h1>Navbar</h1>
</div>
);
}
export default Navigation;
The answer to this tedious question lay within the exportation of the component. The component was not exported correctly. I corrected that by using my way of exporting the footer component folder.
The component index.js was empty, so I just added export { default } from "./Footer";
Thank you all for your answers.

React - Adding a tab to navbar that manipulates page data instead of invoking route redirect

I have a react App and I am using Browser router and a component named Navigation for navigation.
I want to know how to add a tab to the Nav that is not for navigation, but instead allows the user to manipulate a components JSX on a specific page.
I do not know how to structure this. I figure I could use the Context API (maybe?) but before I go down that rabbit hole I figure someone might know a different/better way.
Here is some dummy code
Nav.js
import React from "react";
function Navigation(props){
console.log(props)
return(
<ul>
<li>Landing</li>
<li>Test</li>
<button>Invoke some action on /test</button>
{/* If I am on a page named /test I want this button to have the abillity to trigger a function on that page*/}
</ul>
)
}
export default Navigation
App.js
import React from 'react';
import { BrowserRouter, Route, Redirect } from "react-router-dom";
import Navigation from "./Navigation";
import Test from "./Test";
import { withRouter } from "react-router";
import {Switch} from 'react-router';
import logo from './logo.svg';
import './App.css';
function App(props) {
return (
<div className="App">
<BrowserRouter>
<div>
<Navigation/>
<Switch>
<Route exact path="/test" component={Test} />
<Route exact path="/some-stuff" component={Whatever} />
<Route exact path="/some-more-stuff" component={WhateverElse} />
<Redirect from="/*" to="/test" />
</Switch>
</div>
</BrowserRouter>
</div>
);
}
export default withRouter(App);

Why does the whole DOM re-render when navigating between routes?

I am learning react so forgive me if this has been asked a million times but I have browsed and no solution has fixed my issue. Apart from fixing the issue I would like to understand how the mechanics under the hood work...
I have 2 simple components NavBar and Home. Code below for both.
NavBar:
import React from "react";
class NavBar extends React.Component {
render () {
return (
<nav className="navbar sticky-top navbar-light" style={NavBarStyle}>
<a className="navbar-brand" href="/">
<img src={require('./av_tiny.png')} style={ImageStyle} alt="Logo"></img>
</a>
</nav>
)
}
}
const NavBarStyle = {
// some styling
}
const ImageStyle = {
width: '100px',
height: '50px',
marginLeft: '20px'
}
export default NavBar;
Home:
import React from "react";
class Home extends React.Component {
render(){
return(
<h1>Home</h1>
);
}
}
export default Home;
When I navigate between routes, the whole DOM re-renders. I don't want the NavBar to re-render. My routes are declared in App.js as per below, and I have tried moving <NavBar /> outside the <Router> tags and the other way around. I have also tried putting <NavBar /> in its own <div> tags. Still the app behaves the same, whenever I change the URL it re-renders everything. How can this be avoided and what should I read up to properly understand the mechanics?
import React from 'react';
import {BrowserRouter as Router, Route} from "react-router-dom";
//individual components
import Home from "./Home";
import SignInPage from "./Components/Login";
import NavBar from "./Components/Layout/NavBar"
//Routing to components
class App extends React.Component {
render() {
return(
<div>
<NavBar/>
<Router>
<Route exact path="/" component={Home}/>
<Route exact path="/login" component={SignInPage}/>
</Router>
</div>
)
}
}
export default App;
EDIT:
I think I should've mentioned that re-renders happen when I navigate by manually changing the URL in the browser. I have some code on my /login route that does this.props.history.push('/'); after successful login and the DOM does not re-render. Just {SignInPage} gets unmounted and {Home} gets mounted. I would expect the same behavior when navigating between the pages manually or am I missing something?
You're using <a> elements to create your links. These cause the browser to navigate to the new URL without triggering the JavaScript that would cause the content to be dynamically updated using React.
Use the <Link> component from whatever React Router library you are using instead.
Further reading:
Anchor tags vs Link components in React
The reason why it re-renders hole dom is that the router is changing root properties.
Take a look at nested routers, it will give you an idea of how to achieve your goal Nested routes with react router v4 / v5

How can I run correctly a css-load in react?

I'm learning react and I'm trying to put in my personal project some CSS. I was searching for it and I found several ways to do so:
javascript
npm run eject
// and modifi the path [name]__[local]__[]
import Classes from '.../css/style.css'
//using this method
<link rel="stylesheet" src="./css/styles.css">
// in HTML file
//adding react glamor
Which is the correct way to do it?
Hi only import in the component for example
import './my-style.css'
and in the component jsx call clasname normally
<div className="my-class-css">
...
</div>
Like this:
import React, {Component} from 'react';
import './my-style.css'
class MyComponent extends Component{
render(){
return(
<div className="my-class-css">
....
</div>
)
}
}
export default MyComponent;

React.Children.only expected to receive a single React element child with <Link > component

I am learning react by myself. In my rendering loop I tried to add the element inside so that I can make the hyperlink for each data. But I got this issue:React.Children.only expected to receive a single React element child. Could someone know why it happened? Here is part of my code.Hope it make easier to understand my question. I skipped some parts of my coding as it seems the issue happened in the render part.
app.js
render() {
return (
<Router className="App">
<div>
<nav className="navbar navbar-default">
<div className="container-fluid">
<Link to="/coding-fun">Coding Fun</Link>
</div>
</nav>
<Switch>
// import condingFun.js file as Coding
<Route exact path="/coding-fun" component={Coding} />
<Route path="/coding-fun/:title" component={singleArticle} />
</Switch>
</div>
</Router>
);
}
}
codingFun.js
ps: posts is json data which I didn't add here as too many data.
class Coding extends Component {
render() {
return (
<div className="nav-text">
<h1>Coding fun page</h1>
// posts is data from api, and it renders listPage.js as
ListPage
<ListPage items={posts} />
</div>
);
}
}
export default Coding;
listPage.js
import React, { Component } from "react";
import { BrowserRouter as Link } from "react-router-dom";
class Listing extends Component {
constructor(props) {
super(props);
this.state = { data: this.props.items };
}
render() {
return (
<table>
<tbody>
// loop "post" data from parent component (items) codingFun.js
{this.state.data.map(post => (
<tr key={post.id}>
<td>
<Link to={"coding-fun/" + post.title}>{post.title}</Link>
</td>
<td>{post.content}</td>
</tr>
))}
</tbody>
</table>
);
}
}
If I just add
<Link to={"coding-fun/" + post.title}>{post.title}</Link>
this line, it got "React.Children.only expected to receive a single React element child." issue. If I only add {post.title} in the tag, there is no any issue. So I tried to make the title as link in each row. But I don't know how to make it.
Thanks a lot
The property to does not exist in BrowserRouter. You are also confusing yourself a little bit there by aliasing BrowserRouter with Link because there exists an actual component in react-router called Link. And this is how you use it:
import { Link } from 'react-router-dom'
<Link to={"coding-fun/" + post.title}>{post.title}</Link>
I'm guessing it's because you are doing the import wrong. The import statement should be import { Link } from 'react-router-dom'
You are confusing between Router, Link and Route. So basically,
Router is used to wrap your entire app, to make it fullstack-alike, which means the URL in address bar can be changed and the specific view is rendered respectively
Link is used the same way as <a> tag, which means that it will take you to that URL when clicked
Route, on the other hand, is used to decide what should be rendered under a specific link. This is what you should use to pass children component
In your case, you should change the import statement to:
import { Link } from 'react-router-dom'
Hope this help solve your problem :)

Categories

Resources