React router, <Switch> structure - react-router

I have a React component App which is a child of <Router>. Within App, I am rendering different Components based on the url path using <Switch> and <Route> components.
I know that the role of <Switch> is to render (only) the first matching <Route> component.
My App's render function looks like this.
return (
<Switch>
<Route path='/somepath' component={SomeComponent} />
<Route path='/someotherpath' component={SomeOtherComponent} />
<Main>
<Route path='/anotherpath' component={AnotherComponent} />
<Route component={DefaultComponent} />
</Main>
</Switch>
);
The problem I faced was that when I am rendering AnotherComponent, DefaultComponent is also being rendered.
For now, it seems that wrapping the routes in <Main> into another <Switch> component will enforce the switch behavior. For example,
<Main>
<Switch>
<Route path='/anotherpath' component={AnotherComponent} />
<Route component={DefaultComponent} />
</Switch>
</Main>
So, is it a good practice to nest <Switch> components as I did? Is there a more elegant approach to achieve this?

Related

Why react-bootstrap text-center didn't work ? and why my HR auto center itself if i change the width?

Hi guys so I'm trying to create front-end for my website using react-bootstrap and I try to change my hr width but it auto center itself, why is that ? and also i try to use className="text-center" from bootstrap to center things from my col but it didn't work, can anybody help me with that please ? I already import the bootstrap css but still didn't work.
here's my code:
<Row className="aboutus regular">
<Col className="aboutusleft" lg ="6" >
<h1 className="semibold"> About Us</h1>
<hr style={{width:'20%'}}></hr>
<p>Diamond Hotel serves as an urban oasis for both discerning business and leisure travelers. Located in the heart of Samarinda and close to the most prominent culinary tourism object. The hotel itself possess a trendy design with attention to comfort, quality and value based accommodation. It features 75 modern rooms and suites with contemporary design environment to make you feel completely at home.</p>
<button className="aboutbutton">Learn More</button>
</Col>
<Col className="aboutusright text-center" lg ="4">
<img src="./img/Group4.png"></img>
</Col>
</Row>
My index.js (CSS bootstrap located):
import React from 'react';
import ReactDOM from 'react-dom';
import App from './App';
import 'bootstrap/dist/css/bootstrap.min.css';
ReactDOM.render(
<React.StrictMode>
<App />
</React.StrictMode>,
document.getElementById('root')
);
<Col className="aboutusright mx-auto" lg ="4">
<img src="./img/Group4.png"></img>
</Col>
Please use "mx-auto" instead "text-center".

In react-router, why should the common elements of the page be children of the Router?

In the 1st, basic example in the quickstart, they include the nav (which is common to all routes) in the Router (pasted below for convenience). I can't tell from the code that this is necessary or preferable.
Must I/is it somehow best to likewise put my common components/elements inside the Router?
I suspect this was this simply shorthand to avoid wrapping multiple elements in the return from render (implicit render in this case).
// ...
export default function App() {
return (
<Router>
<div>
<nav>
<ul>
<li>
<Link to="/">Home</Link>
</li>
<li>
<Link to="/about">About</Link>
</li>
<li>
<Link to="/users">Users</Link>
</li>
</ul>
</nav>
{/* A <Switch> looks through its children <Route>s and
renders the first one that matches the current URL. */}
<Switch>
// ...
It looks like I found my answer 😅.
If the common elements/components do not require use of any other react-router components, it should be ok to move them outside. In the linked example, the nav uses the react-router Link component, and so should be inside Router (same is true for other react-router components, e.g. Route

Which is the better document structure?

I am developing several React Projects like below that.
index.js
import ReactDOM from 'react-dom';
import React from 'react';
ReactDOM.render(<App />, getElementById("root"));
App.js
import React from 'react';
const App = () => (
<div className="App">
<header>header</header>
<main>main</main>
<footer>footer</footer>
</div>
);
index.html
<html>
<head>...</head>
<body>
<div id="root"></div>
</body>
</html>
when I built above them, I could get output like below that.
index.html
<html>
<head>...</head>
<body>
<div id="root">
<header>header</header>
<main>main</main>
<footer>footer</footer>
</div>
</body>
</html>
and I wonder whether this Markup Structure is okay.
Because the <body /> tag has <div id="root" /> and it has <header /> and <main /> and <footer />.
I thought it should be changed like below that.
index.html
<html>
<head>...</head>
<body>
<header>header</header>
<main>main</main>
<footer>footer</footer>
</body>
</html>
so, I tried to change my codes like below that.
index.js
import ReactDOM from 'react-dom';
import React from 'react';
ReactDOM.render(<Header />, getElementById("header"));
ReactDOM.render(<App />, getElementById("root"));
ReactDOM.render(<footer />, getElementById("footer"));
App.js
import React from 'react';
const App = () => (<>App</>);
const Header = () => (<>Header</>);
const Footer = () => (<>Footer</>);
index.html
<html>
<head>...</head>
<body>
<header id="header"></header>
<main id="root"></main>
<footer id="footer"></footer>
</body>
</html>
I want to know which structure(?) is better and why.
React tells us why we shouldn't use <body> as the container to mount our App on:
If you try this:
const rootElement = document.body;
ReactDOM.render(<App />, rootElement);
You will get this warning:
Warning: render(): Rendering components directly into document.body is discouraged, since its children are often manipulated by third-party scripts and browser extensions. This may lead to subtle reconciliation issues. Try rendering into a container element created for your app.
That's why you should stick to the root <div id="root">
It will not hurt your website semantic.
https://www.w3schools.com/html/html5_semantic_elements.asp
Examples of non-semantic elements: and - Tells nothing about its content
NOTE: if you do the way that you're suggesting, you'll be needing to mount 3 different components. One for the header, one for the main and one for the footer. How would you share state between them? How would the header component be aware of the state changes that happen on the body component and vice-versa?
From https://reactjs.org/docs/thinking-in-react.html :
Remember: React is all about one-way data flow down the component hierarchy. It may not be immediately clear which component should own what state. This is often the most challenging part for newcomers to understand, so follow these steps to figure it out:
For each piece of state in your application:
Identify every component that renders something based on that state.
Find a common owner component (a single component above all the components that need the state in the hierarchy).
Either the common owner or another component higher up in the hierarchy should own the state.
If you can’t find a component where it makes sense to own the state, create a new component simply for holding the state and add it somewhere in the hierarchy above the common owner component.
What are you worried about, the div wrapping your app? There's no problem with that at all. div (and span) are non-semantic elements, so they don't have any effect on the document structure as such.
This is wrong, don't start your React app like this :)
ReactDOM.render(<Header />, getElementById("header"));
ReactDOM.render(<App />, getElementById("root"));
ReactDOM.render(<footer />, getElementById("footer"));
It bootstraps three separate apps with no way to idiomatically share state amongst them.

React Router Ordering

I had the router specified as below, and having url http://localhost:8000/billing/bill/linematching/c55718e9-9d70-4b65-88ba-fca97d900ca5/693 is able to land on the TBLineMatchingPage
<Route
path="/billing/bill/linematching/:billingRunId"
component={TBCustomersPage}
/>
<Route
path="/billing/bill/linematching/:billingRunId/:accountNumber"
component={TBLineMatchingPage}
/>
But after someone did packages upgrade task, the same url cannot be landed to the TBLineMatchingPage anymore, and I have to move that route on top of TBCustomersPage in order for it to work.
<Route
path="/billing/bill/linematching/:billingRunId/:accountNumber"
component={TBLineMatchingPage}
/>
<Route
path="/billing/bill/linematching/:billingRunId"
component={TBCustomersPage}
/>
Is there a reason why? And what's changed?

Passing Data to Independent Component React

I have this HomeContainer component, Home component and this Header component.
HomeContainer contains the state of city and <Home city={this.props.city} />
Home contains stateless function and contains JSX. so via this.props i can access HomeContainer's city
Problem - I want to send the data to Header so that i can update the city in header whenever someone inputs something in the input field
I think The Main component has access to child components but the Main component is called via routes so i am not able to figure this out.
Thanks
You have a jsx structure similar to:
<Main>
<Header />
<HomeContainer />
</Main>
Since the city property is to be used by both <Header /> and <HomeContainer />, then it shouldn't be defined in <HomeContainer />
city should instead be defined as a state in <Main /> and passed down to both <Header /> and <HomeContainer />
This implies that you also define the callback to changeCity() in <Main /> and pass it down to <HomeContainer /> as a prop.
This way, both <Header /> and </HomeContainer> will be updated with changes to the city attribute