Learning to use the route ReactRouter

 

Refer to the official document: REACT-Router official documents

ReactRouter is a front-end routing implementation, the principle routing on the front end of the follow-up supplement

Router new version is v5, ReactRouter includes three libraries: react-router, react-router-dom and react-router-native.

react-router provides basic routing functions, the actual use, we will not be installed directly react-router, but depending on the application environment running choose to install react-router-dom (using a browser) or react-router-native (in the react-native). react-router-dom and react-router-native depend on the react-router, so that during installation, react-router will automatically installed.

Note: react-router still follow the idea that everything assemblies

Use the browser client

1. Install

yarn add react-router-dom

Note: React Router v4 + is a thorough reconstruction React Router, using dynamic routing, follow React in all are thought components, each Route (route) is a common React components, so v4 + version is not compatible with previous ReactRouter version

2. Routers

Router ReactRouter complete routing through the two components and Route

All routing configuration components are defined as Route Router subcomponents

In Web applications, the general use of the Router will be BrowserRouter or HashRouter two components packed off

BrowserRouter use HTML history API 5 of (pushState, replaceState etc.) synchronization UI and the URL of the application.

HashRouter use the URL hash synchronization UI and the URL of the application.

2.1 Router Components

Router creates a history objects, history is used to track URL, when the URL changes, Router offspring components will be re-rendered.

Other components ReactRouter provided can be obtained through the history object context, this also implies illustrates other components ReactRouter must be used as the descendants of this component Router component. Router but can only have only one child, this component may be custom components, or the first html tags

// 正确  
ReactDOM.render(( 
 <BrowserRouter> 
    <App /> 
 </BrowserRouter>), document.getElementById('root'))  

// 错误,Router 中包含两个子元素
ReactDOM.render(( 
<BrowserRouter> 
    <App1 /> 
    <App2 /> 
</BrowserRouter> ),document.getElementById('root'))

3. Routing Configuration

Route is the highest frequency component, the component whenever there is a need to determine whether the URL when rendering, you need to create a Route, Route components in several common attributes: path and component and render, children, exact, at the same time, component and render , children property is also render component route way, exact path of an exact match and partial match

3.1 path attribute

To configure the routing jumps

When a URL matches Route, that Route defined components will be rendered;

Conversely, Route is not rendered (except for the use of children property render component Route)

When using BrowserRouter, path is used to describe a path name of a URL matching the Route;

When using HashRouter, path is used to describe the URL of the hash matching Route

3.2 component properties

A component for rendering on a matching path,

Component is a component value, and when the URL matching Route, component attribute definition component will be rendered

<Route path='/foo' component={Foo}>

When URL = "http://example.com/foo", Foo components will be rendered

3.3 render property

Render the value is a function may be passed a props parameter, this function returns a React element, it can be easily transferred to the component additional attributes to be rendered, but it also can be a component of the current re-rendered nested route, it is often said secondary, and tertiary routes, etc.

<Route path='/foo' render={(props) =>(       
   <Foo {...props} data={extraProps} />    
)}>

Foo component receives an additional data property

3.4 children property

The value of children is also a function, props can pass a parameter, the function returns React elements to be rendered. The difference is that unlike the other two, regardless of whether the match is successful, children return component will be rendered

<Route path='/foo' children={(props) => (      
 <div>         
    <Foo />       
 </div>     
</Route>

3.5 match property

Route matching URL and when, a match Route created object to the assembly is rendered as an attribute of the props, while the object contains the following four properties

(1) params: Route The path parameters may include, for example, <Routepath = '/ foo /: id'> comprises a parameter id. params is used to resolve the URL matches the parameters of the path, for example, when a URL = "http://example.com/foo/1", params = {id: 1}.

(2) isExact: is a Boolean value, when the URL exactly matches the value of true; when part of the URL match value is false. For example, when the path = "/ foo", URL = "http://example.com/foo", an exact match; URL = time when "http://example.com/ foo / 1", a partial match .

(3) path: Route path property will be used to build routing nested.

(4) url: URL of the matching portion

Demonstration of the use of property on top, and pulled out all routes to a route file, unified management of all routes

1. Create a directory after scaffolding project

Installation Routing

yarn add react-router-dom

App.js

import React from "react";

function App() {
  return (
    <div className="App">
      <header className="App-header">我是App组件</header>
    </div>
  );
}

export default App;

router.js (this file for all the routing configuration file, all routes for the synchronous load)

import React from "react";

import { Route, BrowserRouter } from "react-router-dom";
// 引入组件
import App from "./App";
import SheQu from "./components/SheQu";
import Mine from "./components/Mine";
import News from "./components/News";
const AppRouter = () => (
  <BrowserRouter>
    <Route component={App} path="/" />
    <Route component={SheQu} path="/sq" />
    <Route component={Mine} path="/mine" />
    <Route component={News} path="/news" />
  </BrowserRouter>
);
export default AppRouter;

index.js

import React from "react";
import ReactDOM from "react-dom";
import AppRouter from "./router";
ReactDOM.render(<AppRouter />, document.getElementById("root"));

Compoent contents of the file folders are the same

Mine.js,  News.js,   SheQu.js

import React, { Component } from "react";

export class Mine extends Component {
  render() {
    return <div>个人中心</div>;
  }
}

export default Mine;

Startup project

yarn start

You can see, the page has been shown to render the route, the default rendering "/", which is the default path

Manually modify the path, the page will be changed again on the address bar, such as switching to "/ mine" path

But the question is, no matter how several paths after you switch, the content will be rendered App assembly, which requires the use exact property and Route Switch components of the

When URL and more Route match, the Route will perform rendering operations. If you want to make the first match of Route rendering, you can use these packages to a Route Switch assembly. If you want the URL and Route exact match, Route are rendered, you can use the exact attributes Route, Switch and exact often used in combination

Modify router.js, assembly and use exact Switch

import React from "react";

import { Route, BrowserRouter, Switch } from "react-router-dom";
// 引入组件
import App from "./App";
import SheQu from "./components/SheQu";
import Mine from "./components/Mine";
import News from "./components/News";
const AppRouter = () => (
  <BrowserRouter>
    <Switch>
      <Route component={App} path="/" exact />
      <Route component={SheQu} path="/sq" />
      <Route component={Mine} path="/mine" />
      <Route component={News} path="/news" />
    </Switch>
  </BrowserRouter>
);
export default AppRouter;

In this case of manually switching paths, it is normal

Use render function or children function instead of component attributes, such an approach can still render below

import React from "react";

import { Route, BrowserRouter, Switch } from "react-router-dom";
// 引入组件
import App from "./App";
import SheQu from "./components/SheQu";
import Mine from "./components/Mine";
import News from "./components/News";
const AppRouter = () => (
  <BrowserRouter>
    <Switch>
      {/* <Route children={() => <App />} path="/" exact /> */}
      <Route render={() => <App />} path="/" exact />
      <Route component={SheQu} path="/sq" />
      <Route component={Mine} path="/mine" />
      <Route component={News} path="/news" />
    </Switch>
  </BrowserRouter>
);
export default AppRouter;

4. Jump route

Link and  NavLink are linked component React Router provided a Link component defines when clicking the Link, the page should be how to route

NavLink common attributes

activeClassName: selected by default routing class name

A ctiveStyle: route selected by default style, it is an object

to: Jump to the path

Link attributes:

to: string  path || Object jump

Modify App.js

import React, { Component } from "react";
import { Link } from "react-router-dom";
export class App extends Component {
  render() {
    return (
      <div>
        <ul>
          <li>
            <Link to="/news">新闻</Link>
          </li>
          <li>
            <Link to="/mine">我的</Link>
          </li>
          <li>
            <Link to="/sq">社区</Link>
          </li>
        </ul>
        {this.props.children}
      </div>
    );
  }
}

export default App;

Modify router.js

import React from "react";

import { Route, BrowserRouter, Switch } from "react-router-dom";
// 引入组件
import App from "./App";
import SheQu from "./components/SheQu";
import Mine from "./components/Mine";
import News from "./components/News";

const AppRouter = () => (
  <BrowserRouter>
    <App>
      <Switch>
        <Route component={SheQu} path="/sq" exact />
        <Route component={Mine} path="/mine" />
        <Route component={News} path="/news" />
      </Switch>
    </App>
  </BrowserRouter>
);
export default AppRouter;

Refresh the page, click on the news, you can already jump up

Redirect components using redirection route selected by default news

import React from "react";

import { Route, BrowserRouter, Switch, Redirect } from "react-router-dom";
// 引入组件
import App from "./App";
import SheQu from "./components/SheQu";
import Mine from "./components/Mine";
import News from "./components/News";

const AppRouter = () => (
  <BrowserRouter>
    <App>
      <Switch>
        <Route component={SheQu} path="/sq" exact />
        <Route component={Mine} path="/mine" />
        <Route component={News} path="/news" />
        <Redirect to="/news" />
      </Switch>
    </App>
  </BrowserRouter>
);
export default AppRouter;

The route back to empty the address bar, refresh, selected by default news corresponding components

Jump method

history.push () and history.replace () method

Modify App.js, due App components is not treated as the routing component, it is just a parcel routing nested containers, so there is no history of an object routing in this component, which requires the use withRouter the higher-order component and the component routing binding come in, you can get a print this.props objects of history, 

import React, { Component } from "react";
import { withRouter } from "react-router-dom";
export class App extends Component {
  render() {
    console.log(this.props);
    const { history, children } = this.props;
    return (
      <div>
        <ul>
          <li
            onClick={() => {
              history.push("/news");
            }}
          >
            新闻
          </li>
          <li
            onClick={() => {
              history.push("/mine");
            }}
          >
            我的
          </li>
          <li
            onClick={() => {
              history.push("/sq");
            }}
          >
            社区
          </li>
        </ul>
        {children}
      </div>
    );
  }
}

export default withRouter(App);

Empty, refresh, click, jump the route continues.

5. With regard to page 404, a component is added directly, without any path on the line   <Route component = {NoMatch} / >

import React from "react";

import { Route, BrowserRouter, Switch, Redirect } from "react-router-dom";
// 引入组件
import App from "./App";
import SheQu from "./components/SheQu";
import Mine from "./components/Mine";
import News from "./components/News";
import NoMatch from "./components/AppChild";
const AppRouter = () => (
  <BrowserRouter>
    <App>
      <Switch>
        <Route render={() => <SheQu />} path="/sq" exact />
        <Route component={Mine} path="/mine" />
        <Route component={News} path="/news" />
        <Route component={NoMatch} />
        <Redirect to="/news" />
      </Switch>
    </App>
  </BrowserRouter>
);
export default AppRouter;

6. Routing parameter passing

App.js

history.push("/news?id=10");

import React, { Component } from "react";
import { withRouter, Link } from "react-router-dom";
export class App extends Component {
  render() {
    const { history, children } = this.props;
    return (
      <div>
        <ul>
          <li
            onClick={() => {
              history.push("/news?id=10");
            }}
          >
            新闻
          </li>
          <li>
            <Link to="/mine/10"> 我的</Link>
          </li>
          <li
            onClick={() => {
              history.push("/sq");
            }}
          >
            社区
          </li>
        </ul>
        {children}
      </div>
    );
  }
}

export default withRouter(App);

News.js

import React, { Component } from "react";
export class News extends Component {
  render() {
    console.log(this.props);
    return <div>我是news 新闻</div>;
  }
}
export default News;

And then obtaining location parameters on dynamic routing, see the official example, the following is not elaborated


Some knowledge integration of routing, to stop practicing real projects

Home, News, community, my, 404 pages, news details page, table of contents as follows

index.js

import React from "react";
import ReactDOM from "react-dom";
import AppRouter from "./router";
ReactDOM.render(<AppRouter />, document.getElementById("root"));

App.js

import React, { Component } from "react";
import { withRouter } from "react-router-dom";
import "./css/app.css";
export class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      navList: [
        {
          id: 1,
          name: "首页",
          path: "/"
        },
        {
          id: 2,
          name: "新闻",
          path: "/news"
        },
        {
          id: 3,
          name: "社区",
          path: "/sq"
        },
        {
          id: 4,
          name: "我的",
          path: "/mine"
        }
      ]
    };
  }
  render() {
    const { children } = this.props;
    const { navList } = this.state;
    return (
      <div className="app">
        <ul>
          {navList.map(item => (
            <li
              key={item.id}
              onClick={() => this.props.history.push(item.path)}
            >
              {item.name}
            </li>
          ))}
        </ul>
        <div>{children}</div>
      </div>
    );
  }
}

export default withRouter(App);

app.css

body {
    margin: 0;
    padding: 0;
}

.app ul {
    display: flex;
    margin: 0;
    background-color: #ccc;
}

.app ul li {
    list-style: none;
    padding: 10px;
    cursor: pointer;
}

.News {
    display: flex;
}

.news {
    display: block !important;
    background-color: #fff !important;
    border: 1px solid #666;
    width: 400px;
    margin: 10px !important;
}

.newsInfor {
    width: 500px;
    background-color: #eee;
    height: 300px;
}

components folder

Home.js, MIne.js, SheQu.js, change to change the content of their own, ah, all the same


export class Home extends Component {
  render() {
    return <div>我是首页</div>;
  }
}

export default Home;

router.js

import React from "react";

import { Route, BrowserRouter, Switch } from "react-router-dom";
// 引入组件
import App from "./App";
import SheQu from "./components/SheQu";
import Home from "./components/Home";
import Mine from "./components/Mine";
import News from "./components/News";
import NoMatch from "./components/NoMatch";
const AppRouter = () => (
  <BrowserRouter>
    <App>
      <Switch>
        <Route component={Home} path="/" exact />
        <Route component={Mine} path="/mine" />
        <Route component={News} path="/news" />
        <Route component={SheQu} path="/sq" />
        <Route component={NoMatch} />
      </Switch>
    </App>
  </BrowserRouter>
);
export default AppRouter;

News.js

import React, { Component } from "react";

export class News extends Component {
  constructor(props) {
    super(props);
    this.state = {
      newsList: [
        {
          id: 1,
          title: "hello , im in the world1 ?"
        },
        {
          id: 2,
          title: "hello , im in the world2 , you are OK ?"
        },
        {
          id: 3,
          title: "hello , im in the world3, China is Good ? "
        },
        {
          id: 4,
          title: "hello , im in the world4 ,english is bad?"
        }
      ]
    };
  }
  itemHandle(id) {
    
  }
  render() {
    return (
      <div className="News">
        <ul className="news">
          {this.state.newsList.map(item => (
            <li key={item.id} onClick={() => this.itemHandle(item.id)}>
              {item.title}
            </li>
          ))}
        </ul>
        <div className="newsInfor">{this.props.children}</div>
      </div>
    );
  }
}

export default News;

Start the service, click on the news, Home, and so on to switch it

Click on the list of news, News Details

Add newsInfor.js

import React, { Component } from "react";

export class newsInfor extends Component {
  constructor(props) {
    super(props);
    this.state = {
      newsInforList: [
        {
          id: 1,
          infor: "我是第一个hello world"
        },
        {
          id: 2,
          infor: "我是第二个hello world"
        },
        {
          id: 3,
          infor: "我是第三个hello world"
        },
        {
          id: 4,
          infor: "我是第四个hello world"
        }
      ]
    };
  }
  filterNews() {
    let id = this.props.match.params.id;
    const { newsInforList } = this.state;
    return newsInforList.filter(item => {
      return item.id === Number(id);
    });
  }
  render() {
    return (
      <div>
        {this.filterNews().map(item => (
          <p key={item.id}>{item.infor}</p>
        ))}
      </div>
    );
  }
}

export default newsInfor;

Modify router.js

import React from "react";

import { Route, BrowserRouter, Switch } from "react-router-dom";
// 引入组件
import App from "./App";
import SheQu from "./components/SheQu";
import Home from "./components/Home";
import Mine from "./components/Mine";
import News from "./components/News";
import NoMatch from "./components/NoMatch";
import newsInfor from "./components/newsInfor";
const AppRouter = () => (
  <BrowserRouter>
    <App>
      <Switch>
        <Route component={Home} path="/" exact />
        <Route component={Mine} path="/mine" />
        <Route component={News} path="/news" />
        <Route component={newsInfor} path="/newsInfor/:id" />
        <Route component={SheQu} path="/sq" />
        <Route component={NoMatch} />
      </Switch>
    </App>
  </BrowserRouter>
);
export default AppRouter;

News.js the completion event callback function

import React, { Component } from "react";

export class News extends Component {
  constructor(props) {
    super(props);
    this.state = {
      newsList: [
        {
          id: 1,
          title: "hello , im in the world1 ?"
        },
        {
          id: 2,
          title: "hello , im in the world2 , you are OK ?"
        },
        {
          id: 3,
          title: "hello , im in the world3, China is Good ? "
        },
        {
          id: 4,
          title: "hello , im in the world4 ,english is bad?"
        }
      ]
    };
  }
  itemHandle(id) {
    this.props.history.push(`/newsInfor/` + id);
  }
  render() {
    return (
      <div className="News">
        <ul className="news">
          {this.state.newsList.map(item => (
            <li key={item.id} onClick={() => this.itemHandle(item.id)}>
              {item.title}
            </li>
          ))}
        </ul>
        <div className="newsInfor">{this.props.children}</div>
      </div>
    );
  }
}

export default News;

Hit the jump, you can see the data to get the news details

Nested routing

Modify router.js

import React from "react";

import { Route, BrowserRouter, Switch } from "react-router-dom";
// 引入组件
import App from "./App";
import SheQu from "./components/SheQu";
import Home from "./components/Home";
import Mine from "./components/Mine";
import News from "./components/News";
import NoMatch from "./components/NoMatch";
import newsInfor from "./components/newsInfor";
const AppRouter = () => (
  <BrowserRouter>
    <App>
      <Switch>
        <Route component={Home} path="/" exact />
        <Route component={Mine} path="/mine" />
        <Route
          render={props => (
            <News {...props}>
              <Route path="/news/newsInfor/:id" component={newsInfor} />
            </News>
          )}
          path="/news"
        />
        <Route component={SheQu} path="/sq" />
        <Route component={NoMatch} />
      </Switch>
    </App>
  </BrowserRouter>
);
export default AppRouter;

Modify News.js

import React, { Component } from "react";

export class News extends Component {
  constructor(props) {
    super(props);
    this.state = {
      newsList: [
        {
          id: 1,
          title: "hello , im in the world1 ?"
        },
        {
          id: 2,
          title: "hello , im in the world2 , you are OK ?"
        },
        {
          id: 3,
          title: "hello , im in the world3, China is Good ? "
        },
        {
          id: 4,
          title: "hello , im in the world4 ,english is bad?"
        }
      ]
    };
  }
  itemHandle(id) {
    this.props.history.push(`/news/newsInfor/` + id);
  }
  componentDidMount() {
    this.props.history.push(`/news/newsInfor/` + this.state.newsList[0].id);
  }
  render() {
    return (
      <div className="News">
        <ul className="news">
          {this.state.newsList.map(item => (
            <li key={item.id} onClick={() => this.itemHandle(item.id)}>
              {item.title}
            </li>
          ))}
        </ul>
        <div className="newsInfor">{this.props.children}</div>
      </div>
    );
  }
}

export default News;

Combat 2, processing is logged in, to determine the route display

Login.js

import React, { Component } from "react";

export class Login extends Component {
  render() {
    return (
      <div className="login">
        <input type="text" />
        <br />
        <input type="password" />
        <br />
        <button onClick={this.login}>登录</button>
      </div>
    );
  }
  login = () => {
    //   存储登录标志
    localStorage.setItem("isLogin", true);
    this.props.history.push("/app");
  };
}

export default Login;

router.js

Of course, you can also re-routed here by Miki operation, to determine if and so too, come directly, if not, redirect to the login page

import React from "react";

import { Route, BrowserRouter, Switch, Redirect } from "react-router-dom";
// 引入组件
import App from "./App";
import SheQu from "./components/SheQu";
import Home from "./components/Home";
import Mine from "./components/Mine";
import News from "./components/News";
import NoMatch from "./components/NoMatch";
import newsInfor from "./components/newsInfor";
import Login from "./components/Login";
const AppRouter = () => (
  <BrowserRouter>
    <Switch>
      <Route component={Login} path="/" exact />
      <Route
        path="/app"
        render={props => (
          <App {...props}>
            <Switch>
              <Route component={Home} path="/app/home" />
              <Route component={Mine} path="/app/mine" />
              <Route
                render={props => (
                  <News {...props}>
                    <Route
                      path="/app/news/newsInfor/:id"
                      component={newsInfor}
                    />
                  </News>
                )}
                path="/app/news"
              />
              <Route component={SheQu} path="/app/sq" />
              <Route component={NoMatch} />
            </Switch>
          </App>
        )}
      />
    </Switch>
  </BrowserRouter>
);
export default AppRouter;

News.js

import React, { Component } from "react";

export class News extends Component {
  constructor(props) {
    super(props);
    this.state = {
      newsList: [
        {
          id: 1,
          title: "hello , im in the world1 ?"
        },
        {
          id: 2,
          title: "hello , im in the world2 , you are OK ?"
        },
        {
          id: 3,
          title: "hello , im in the world3, China is Good ? "
        },
        {
          id: 4,
          title: "hello , im in the world4 ,english is bad?"
        }
      ]
    };
  }
  itemHandle(id) {
    this.props.history.push(`/app/news/newsInfor/` + id);
  }

  render() {
    return (
      <div className="News">
        <ul className="news">
          {this.state.newsList.map(item => (
            <li key={item.id} onClick={() => this.itemHandle(item.id)}>
              {item.title}
            </li>
          ))}
        </ul>
        <div className="newsInfor">{this.props.children}</div>
      </div>
    );
  }
}

export default News;

App.js

import React, { Component } from "react";
import { withRouter } from "react-router-dom";
import "./css/app.css";
export class App extends Component {
  constructor(props) {
    super(props);
    this.state = {
      navList: [
        {
          id: 1,
          name: "首页",
          path: "/app/home"
        },
        {
          id: 2,
          name: "新闻",
          path: "/app/news"
        },
        {
          id: 3,
          name: "社区",
          path: "/app/sq"
        },
        {
          id: 4,
          name: "我的",
          path: "/app/mine"
        }
      ]
    };
  }
  componentDidMount() {
    // 获取是否登录的标志
    const { history } = this.props;
    let islogin = localStorage.getItem("isLogin");
    if (islogin) {
      history.push("/app/home");
    } else {
      history.push("/");
    }
  }
  render() {
    const { children } = this.props;
    const { navList } = this.state;
    return (
      <div className="app">
        <ul>
          {navList.map(item => (
            <li
              key={item.id}
              onClick={() => this.props.history.push(item.path)}
            >
              {item.name}
            </li>
          ))}
        </ul>
        <div>{children}</div>
      </div>
    );
  }
}

export default withRouter(App);

app.css

body {
    margin: 0;
    padding: 0;
}

.app ul {
    display: flex;
    margin: 0;
    background-color: #ccc;
}

.app ul li {
    list-style: none;
    padding: 10px;
    cursor: pointer;
}

.News {
    display: flex;
}

.news {
    display: block !important;
    background-color: #fff !important;
    border: 1px solid #666;
    width: 400px;
    margin: 10px !important;
}

.newsInfor {
    width: 500px;
    background-color: #eee;
    height: 300px;
}

.login {
    margin: 300px;
}

Click refresh to jump right

Summary: When react with the route for development, you can first draw a sketch that he had about a flow chart, and then design the route, it will be well understood, clear some routes designed for everyone is not the same, nor the specific wording same

 

 

 

 

 

Published 63 original articles · won praise 100 · views 310 000 +

Guess you like

Origin blog.csdn.net/qq_36407748/article/details/90230066