React note #15

Yechan Jeon·2021년 12월 30일
0

React dev

목록 보기
12/18
post-thumbnail

Multi page with React


Routing

In real word example, There is lots of routes in web page which is handled by Server. Of course, we should show different visual content of each paths.

We still want to build Sinlge Page App in react. With that reason, we will handle path changes with react-code and change visible content as to those paths without fetching a new HTML file like vanilla javascript web page.

React router (third-party package)

npm install react-router-dom

React router v5

The process will be like this :
domain.com/products -> components related to products
domain.com/contacts -> components related to contacts
and so on.
We will render each components according to routes.

  1. Go to index.js and wrap rendered component with BrowserRouter element.
import ReactDOM from "react-dom";
import { BrowserRouter } from "react-router-dom";
import "./index.css";
import App from "./App";

ReactDOM.render(
  <BrowserRouter>
    <App />
  </BrowserRouter>,
  document.getElementById("root")
);
  1. import Route
    import { Route } from "react-router-dom";
  2. set path prop in Route and give component
<Route path="/welcome">
        <Welcome />
      </Route>

This Route element will allow for Welcome element to be shown only in '/welcome path'

  1. For better UX, you can set link in your app. If you use common <a href="">, your app will send request every time user click it.
    So there is built-in component in 'react-router-dom' to prevent this and keep SPA style.
    Wrap link with 'Link' component and give 'to' prop url
import { Link } from "react-router-dom";
.
.
  <li>
      <Link to="/welcome">Welcome</Link>
 </li>
 <li>
      <Link to="/products">Products</Link>
</li>
  1. If the link is in navigation, it may need active style (this tell user where they are)
    Import 'Navlink' from 'react-router-dom' and give prop 'activeClassName', then set active style in css.
          <li>
            <NavLink activeClassName={classes.active} to="/welcome">
              Welcome
            </NavLink>
          </li>
          <li>
            <NavLink activeClassName={classes.active} to="/products">
              Products
            </NavLink>
          </li>
  1. Dynamic Routes
    You can set params in url
  • setting
        <Route path="/product-detail/:productId">
          <ProductDetail />
        </Route>
  • use
    import 'useParams' from 'react-router-dom'
const params = useParams();

  return (
    <section>
      <h1>Product Detail</h1>
      <p>{params.productId}</p>
    </section>
  );
  1. Switch and exact
    React router originally activate all routes which is matched with current path.
    If you are using '/products' for whole products and '/products/:id' for detail view, you will override detail view on whole products page. you even set id though.
    So you need Switch and exact.
    Wrap elements which you want to separate with Switch and give 'exact' prop to a route which lead descendents.
<Switch>
          <Route path="/products" exact>
            <Products />
          </Route>
          <Route path="/products/:productId">
            <ProductDetail />
          </Route>
</Switch>
  1. Nested Route.
    you can set Route in Route.
    Nested Route will be accesible when upper Route is activated.
  • App.js
          <Route path="/welcome">
            <Welcome />
          </Route>
  • welcome.js
const Welcome = () => {
  return (
    <section>
      <h1>The Welcome page</h1>
      <Route path="/welcome/new-user">
        <p>Welcome, stranger</p>
      </Route>
    </section>
  );
};
  1. Redirect
    import {Redirect} from 'react-router-dom'
    Give path to where you wannt apply redirect and set Redirect element in there.
          <Route path="/" exact>
            <Redirect to="/welcome" />
          </Route>
  1. Navigate after some action programatically
    import {useHistory} from 'react-router-dom'
    This hook contains history of browser page which user visited.
    It has 'push' and 'replace' method.
    push method allow user to go back.
    replact is like a redirect.
    This is not something like link , it is an action triggered by code. That's why it is called as navigation programatically
const AddQuote = () => {
  const history = useHistory();
  const addQuotehandler = (quoteData) => {
    console.log(quoteData);
    history.push("/quotes");
  };
  return <QuoteForm onAddQuote={addQuotehandler} />;
};
  1. How to prevent unwanted router move
    When user writing in form and if suddenly they move to another route, user will lose everything that they wrote in form.
    To prevent this, we can use 'Prompt' component
    <Prompt when={isEntered} message={() => "정말로 떠나시겠습니까?"} />
    This Component will execute prompt according to 'when' prop.
    Here i defined 'isEntered' state and if user click form , the state will be changed as true.
          onFocus={formFocusHandler}
          className={classes.form}
          onSubmit={submitFormHandler}
        >

Because the state changed to true when user click form, if user move to another route unexpectedly, Prompt message will prevent that.

  1. Query string
    With help of useHistory and useLocation hook, we can set and get query string in URL
  const history = useHistory();
  const location = useLocation();

  const queryParams = new URLSearchParams(location.search);

  const changeSortingHandler = () => {
    history.push("/quotes?sort=" + (isSortingAscending ? "desc" : "asc"));
  };
  1. Flexible routing
    use 'useRouteMatch' hook
    It has property of path of current location
  • before
<Route path={`/quotes/${params.id}`} exact>

-after

const match = useRouteMatch();

<Route path={match.path} exact>

React router ver 6

  1. Switch -> Routes

  2. There is no child component in Route

  • before
<Route path='/welcome' >
  <Welcome />
</Route>

-after

<Route path='/welcome' element={<Welcome />} />
  1. Order of routers doesn't matter anymore (algorithm improvement)

  2. activeClassName prop removed -> must manually set

<NavLink className={(navData) => navData.isActive ? classes.active : '' }
  1. ->
    If you want full redirect,

  2. Nested route
    You should wrap Nested route with '' and add star in upper Router.
    You don't need repeat duplicated part of route in nested routes.

  • upper Router
<Route path="/welcome/*" element={<Welcome />}/>
  • Nested Router(in Welcome.js)
const Welcome = () => {
//some code
  //nested part
<Routes>
  <Route path="/new-user" element={something} />
</Routes>
//some code
}
  1. No need of Custom path resolving
    We selected flexible routing in version 5, but here in version 6, Router understand what's going on under that router, So there is no need repeating duplicated route.
<Link to="/products/detail"> -> <Link to="/detail">
<Route path={`${match.path}/comments`}> -> <Route path="/comments">
  1. Different approach of nested route
    Give nested route as a children and import it as an Outlet component
  • upper
<Route path="/welcome/*" element={<Welcome />}/>
	<Route path="/new-user" element={something} />
</Route>
  • Welcome.js
import {Outlet} from 'react-router-dom'

const Welcome = () => {
//some code
  //nested partsss
	<Outlet />
//some code
}
  1. useHistory -> useNavigate
const navigate = useNavigate();
navigate('/welcome') // move to path
navigate('/welcome', {replace: true}) // fully redirect
navigate(number) // move back or forward by given number
  1. Prompt component is not supported in version 6
profile
방황했습니다. 다시 웹 개발 하려고요!

0개의 댓글