I have a react application. The App.js fragment is as follow:
import ServiceManual from './components/pages/ServiceManual'
import './App.css';
const App = () => {
return (
<>
<Router>
<Switch>
<Route path='/ServiceManual' exact component={ServiceManual} />
<Route path='/' exact component={Home} />
</Switch>
</Router>
</>
)
};
The ServiceManual component contains it's own ServiceManual.module.css
import React from 'react';
import { Container } from 'react-bootstrap';
import '../App.css';
import './ServiceManual.module.css';
export default function ServiceManual() {
return <Container fluid className="mainPage">
....
Now, my problem is that some definitions contained into the ServiceManual.module.css influence the content of my Home page.
It looks like the import of the component in the App.js build an enormous container where all the imported definition will finish.
I found on the internet the suggestion to name xxx.module.css instead of xxx.css a .css file that has to be used just in the module where it is imported. But this is not true.
When I open the browser debugger on my home page I see some .css definitions (defined in xxx.module.css) that shouldn't be there and that change the way my homepage is displayed.
Has anyone a hint, please?
The truth is, all CSS files are included in the page as long as they are imported, no matter where.
If you need different styles for different elements, give them unique class names and handle them by their class names in their various CSS scripts.
Related
As stated in the title I am trying to create a layout component but using any react-bootstrap components seems to give me errors. In this case, using I get the error:
TypeError: Cannot read properties of null (reading 'useContext')
The code for this Layout component is below:
import React from 'react';
import { Container } from 'react-bootstrap';
export const Layout = (props) => (
<Container>
{props.children}
</Container>
)
And this is being called from App.js below:
import React, { Component } from 'react';
import { BrowserRouter as Router, Route, Switch } from 'react-router-dom';
import { Layout } from './components/Layout';
import { Home } from './components/Home';
import './custom.css'
class App extends Component {
render () {
return (
<Layout>
<Switch>
<Router>
<Route exact path='/' component={Home} />
</Router>
</Switch>
</Layout>
);
}
}
export default App;
Replacing the container tags with div renders as expected but any use of react-bootstrap causes the useContext error.
Router must be above Switch:
<Router>
<Layout>
<Switch>
<Route path="/" component={Home} />
</Switch>
</Layout>
</Router>
https://codesandbox.io/s/determined-zeh-r3vvl4
One possible reason of such error is to have multiple versions of react. This can be checked by a shell command like find . -name react.
A second (and unintended) version of react could be introduced as transitive dependency, or from some tricky package resolution process.
How to eliminate multiple versions depend on the package manager you use. npm has package.json overrides and npm dedup, yarn has resolutions, and so on.
I think the issue is how you import it.
import Container from 'react-bootstrap/Container'
I got the same error, I fixed that by updating my bootstrap version.
I have several questions about React.Suspense.
Here is some example code for reference:
// components/ComponentA/index.js
import React from "react";
const style = {
display: "grid",
placeItems: "center"
};
export default function ComponentA() {
return <div style={style}>I am componentA</div>;
}
// components/ComponentB/index.js
import React from "react";
const style = {
display: "grid",
placeItems: "center"
};
export default function ComponentB() {
return <div style={style}>I am componentB</div>;
}
// App.js
import React from "react";
import "./styles.css";
const ComponentA = React.lazy(() => import("./components/ComponentA"));
const ComponentB = React.lazy(() => import("./components/ComponentB"));
export default function App() {
const [state, toggleState] = React.useReducer((state) => !state, false);
return (
<div className="App">
<button onClick={toggleState}>click to show</button>
<React.Suspense fallback={<div>Loading...</div>}>
{state ? <ComponentA /> : <ComponentB />}
</React.Suspense>
</div>
);
}
When running this code, I've noticed several things right away.
The first thing I noticed is that when the app loads for the first time, there is a split moment where you can see loading... before I am componentB is rendered.
The second thing I noticed is that if you click the button, you can, again, for a split moment see loading... before I am componentA is rendered on the screen.
I assume this is the expected result with dynamic imports.
The final thing that I noticed is that continuing to toggle the button, I never see loading... again. I assume that this is because the components have already been imported and used by the client. Which is, I also assume, expected behavior.
My three questions here are,
am I using React's dynamic imports correctly (or should I use import elsewhere) and,
when should React.Suspense and dynamic imports be used
If the components are relatively simple, do I need to even consider lazy loading components?
Sandbox for reference
For the First question -
Yes, you are using the lazy() function to import components Correctly.
For the second question -
From the React docs,
Suspense lets components “wait” for something before rendering.
It is used to improve your site's performance with regards to its First Contentful Paint and Loading times on slow or bad networks, as well as for asynchronous tasks like data fetching where your component depends on the data returned so you show a Loading.. message to the user as a Fallback.
For example, a component which I have written and used-
import React, { Component, lazy, Suspense } from "react";
import { Route, Switch } from "react-router-dom";
import Error404 from "./Error404";
import LoadingSpinner from "./LoadingSpinner";
const Dashboard = lazy(() => import("./Dashboard"));
const Employees = lazy(() => import("./EmployeesPage"));
class Container extends Component {
//handles paths '/' and '/employees' along with any unknown paths
render() {
return (
<div id="container">
<div id="background">
</div>
<div id="content">
<Switch>
<Route exact path="/">
<Suspense fallback={<LoadingSpinner />}>
<Dashboard />
</Suspense>
</Route>
<Route path="/employees">
<Suspense fallback={<LoadingSpinner />}>
<Employees />
</Suspense>
</Route>
<Route component={Error404} />
</Switch>
</div>
</div>
);
}
}
export default Container;
Here, I am lazy loading my two components Dashboard and Employees which in themselves contain many components and are relatively complex.
Lazy loading them prevents the connection to be clogged while loading the site for the first time.
These components are now loaded only when the user navigates to the specified URL by some NavLinks.
Since it's safe to assume that the user will spend some time in the Dashboard before going to the Employees page(at least in my app), this approach works fine.
For the third question -
If you have components that you are sure will be needed when the site loads, it's better to not lazy load them to keep the User Experience good.
Small components (by their bundle size) don't need lazy loading, only when you think that many components are gonna be used only rarely, then you can lazy load them in one bundle.
Lastly -
You can open up the Network tab on the developer tools of a browser and see the bundles loading in as the user requests for them (React handles that in lazy()). The Bundles are labelled like this- Network Tab screenshot
Hope you find the answer useful and any recommendations for the post are appreciated✌
Here's my code for my App.js :
import './App.css';
import { BrowserRouter as Router, Route, } from "react-router-dom";
import Navbar from './Components/Navbar';
import Education from './contents/Education';
function App() { return (
<Router>
{/* route navbar */}
<div className="App">
<Navbar />
{/* route 2 home */}
<Route exact path="/Home">
< Home />
</Route>
{/* Route for About.js contents */}
<Route path="/About">
< About />
</Route>
{/* route to widecard */}
<Route path="/Education">
<Education />
</Route>
</div>
</Router>
)
}
export default App;
When I run npm start in my terminal I get this error:
./src/App.js
Line 18:7: 'Home' is not defined react/jsx-no-undef
Line 26:7: 'About' is not defined react/jsx-no-undef
I have a Home.js and an About.js... I'm still learning react so if this seems like a simple fix I'm sorry in advance! Please let me know if any more information needs to be provided.
Thanks everyone!
You don't import Home or About at the top of the file. IF you import those in, I think you'll be good to go.
Also < Home /> shouldn't have a space between the open bracket and the name. Should be <Home />.
You need to import the componant (Home and About) so you can use then.
Home.js and About.js should contain an export , and App.js should contain
import Home from 'path/to/Home/Home' //(you dont need to write the .js)
And same with About
As with using any component it must first be exported then imported. As it appears that the later was overlooked in your code.
import About from '..relative path to -> /About'
import Home from '..relative path to -> /Home'
When you import something from other modules be sure to mention that function .I assume you know this fact but these mistakes can happen
i.e
import Home from "./pages/home/Home"
I am trying to conditionally redirect to other pages within a modal using from react-router.
I have implemented withRouter at the bottom of the relevant components as well as in the connect function. I am currently not using the Reducer because I have a switch in a root modal component which catches a type and then renders a component. Below is a snippet from the switch.
case type.componentName
return <Redirect to='/component' />
break;
However, the new component is still not rendering. It is as if Redirect is not being registered at all. My route is below.
<App>
<Switch>
<Route path="/" component={HomePage} />
<Route component={upperComponent}>
<Route path="/modal" component={rootComponent}>
<Route path="/component" component={component} />
</Route>
</Route>
</Switch>
</App>
I was originally rendering pages by modifying the state through a boolean and based upon it, a different component would be rendered. This worked just fine but I would rather have some history from using React-Router when I render new pages. Is there something fundamentally wrong about how I am trying to call Redirect or should I use an entirely different strategy all together?
The code below was requested in a comment. This is in my container component and I have one per component.
import { bindActionCreators } from 'redux';
import { connect } from 'react-redux';
import rootComponent from '../components/rooComponent';
import { withRouter } from 'react-router-dom';
import * as rootComponentlActions from '../actions/rootComponent';
function mapStateToProps(state) {
return {
};
}
function mapDispatchToProps(dispatch) {
return bindActionCreators(rootComponentActions, dispatch);
}
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(rootComponent));
I have also tried adding export default withRouter(component); as well in my child component to the root as well as in the root to test it out based upon some examples that I have read in the past. As far as I can tell, it made not difference, good or bad.
When I run the my app on browser I get on my console:
"Warning: Failed propType: Invalid prop 'component' supplied to
'route'"
My routes file:
import { Route, IndexRoute } from 'react-router';
import React from 'react';
import App from './container/App';
import PContainer from './container/PContainer/PContainer';
import PView from './container/PView/PView';
const routes = (
<Route path="/" component={App} >
<IndexRoute component={PContainer} />
<Route path="/Posts View" component={PView} />
</Route>
);
export default routes;
My PView file:
import React, { Component, PropTypes } from 'react';
import { connect } from 'react-redux';
class PView extends Component {
render() {
return (
<div>
<h1>List of Posts</h1>
</div>
);
}
}
export default connect()(PView);
Can anyone tell me why I am getting this error?
I met the same issue as you.
When I put a connect() component into <Route />, this warning must be there. If the component is not a connect() one, then the issue will not be there.
Solution
You can change the line
<Route path="/Posts View" component={PView} />
to
<Route path="/Posts View" render={(props) => <PView {...props} />} />
then the issue should go away.
Thinking
Look at the document of React-router
component should be used when you have an existing component (either a
React.Component or a stateless functional component) that you want to
render. render, which takes an inline function, should only be used
when you have to pass in-scope variables to the component you want to
render.
So when you would like to define a route of connect() component, you are implicitly going to pass some additional props into it, then according to the document you should use render instead of component. I guess this is the reason of warning happened.
Make sure that App, PContainer, and PView are all valid React components. Check module's imports and exports. Export should be with "default", otherwise you should use named import: import {somecomp} from './somecomp'. Check your routes to components.
Your routes look a bit weird: './container/PContainer/PContainer' and './container/PView/PView'.
Maybe it should be './container/PContainer' and './container/PView', if you don't have PContainer and PView folders.
Recently, I have been through this issue. I found that if you have any imported component which is empty or returning nothing then this issue arises because react could not consider it as a valid component.
Have a look if you have any component that you might have left empty.