React入门4

Posted 临风而眠

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了React入门4相关的知识,希望对你有一定的参考价值。

React入门4

文章目录

下面使用函数式组件

一.路由基本配置

  • 在刚刚那个项目的src文件夹下面新增pages文件夹用于放页面

    components文件夹用于放组件

    App.js改为Demo1.js并放入pages文件夹

    app.text.js、index.js 和logo.svg删除

    index.css删除,App.js删除后要

    在index.js里面把引入的语句删除

    这里也要删

    否则会报错

建立路由

建立各个页面

  • 安装插件

    yarn add react-router-dom --save
    
  • 在src目录下新建router.js

    • 导入组件
    import  BrowserRouter as Router,Route   from "react-router-dom";
    //重命名为Router,Route
    export default function IRouter() 
        return (
        <Router>
            //子路由
                <Route path="/" component=A></Route>
                <Route path="/login" component=B></Route>
                <Route path="/home" component=C></Route>
        </Router>);
    
    
    

    那个应该也是解构的写法?

    参考:react中对import React,Component from 'react’写法的解释,以及react中常见import的用法

    • 在pages里面新建三个页面

  • 新建的app.js

    import React from "react";
    
    
    export default function App() 
        return (
            <div>This is App</div>
        );
    
    

    login.js

    import React from "react";
    
    
    export default function Login() 
        return (
            <div>This is Login</div>
        );
    
    

    home.js

    import React from "react";
    
    
    export default function Home() 
        return (
            <div>This is Home</div>
        );
    
    
  • 组件的加载

    在router.js里面引入刚刚那三个页面

    import App from "./pages/app"
    import Login from "./pages/login"
    import Home from "./pages/home"
    

    感谢弹幕!

    import  BrowserRouter as Router,Route ,Routes  from "react-router-dom";
    //重命名为Router,Route
    import React from "react"
    import App from "./pages/app"
    import Login from "./pages/login"
    import Home from "./pages/home"
    
    export default function IRouter() 
        return (
        <Router>
            /* //子路由 */
                <Routes path="/" element=<App/>/>
                <Routes path="/login" element=<Login/>/>
                <Routes path="/home" element=<Home/>/>
        </Router>);
    
    
    

    参考:

    React中的路由react-router

    试着按照弹幕改了改,但报了这个错

    嘿嘿 这段时间学了英语,终于能耐心地去看StackOverflow了

    参考:React Router V6 - Error: useRoutes() may be used only in the context of a component

    解决:

    import  BrowserRouter, Route ,Routes  from "react-router-dom";
    //重命名为Router,Route
    import React from "react"
    import App from "./pages/app"
    import Login from "./pages/login"
    import Home from "./pages/home"
    
    export default function IRouter() 
        return (
        <BrowserRouter>
            <Routes>
            /* //子路由 */
                <Route path="/" element=<App/>/>
                <Route path="/login" element=<Login/>/>
                <Route path="/home" element=<Home/>/>
                </Routes>
           </BrowserRouter> );
               
    
    
    

    记得修改index.js

    返回的组件改为Router

    import React from 'react';
    import ReactDOM from 'react-dom';
    import Router from './router'
    import reportWebVitals from './reportWebVitals';
    
    ReactDOM.render(
      <React.StrictMode>
        <Router/>
      </React.StrictMode>,
      document.getElementById('root')
    );
    
    • 效果

      localhost:3000

      localhost:3000/login 则显示 This is Login

  • 精准匹配

    我好像没遇到这个问题,不过视频里的老版本遇到了问题

    就是匹配的时候会受到第一个"/"的影响

    按照视频里说的Switch,结果热重载的时候说:

    在StackOverflow上看到了解答

    原来就是Routes啊…

     < Routes >
                    <Route exact path="/" element=<App /> />
                    <Route exact path="/login" element=<Login /> />
                    <Route exact path="/home" element=<Home/>/>
            </Routes>
    

    path原先已经没有视频里那个问题了,exact path就更没问题啦

实现跳转

把原先的App.scss改为Demo1.scss

新增app.scss

  • 在app.js里面使用Link组件

    import React from 'react'
    import  Link  from 'react-router-dom'
    
    export default function App() 
        return (
            <div className="container">
    			<h1>路由跳转学习</h1>
                <Link to="/login">点击跳转到登陆页面</Link>
                <Link to="/home">点击跳转到主页面</Link>
        
            </div> 
        );
    
    

    注意div那里写className,不要写class

  • 加点样式

    在app.scss写入:

    .container,
    div 
      padding-top: 100px;
      font-size: 28px;
      text-align: center;
      a 
        font-size: 26px;
      
    
    
    

    然后在app.js引入app.scss

    import React from 'react'
    import  Link  from 'react-router-dom'
    import './app.scss'
    export default function App() 
        return (
            <div className="container">
                <h1>路由跳转学习</h1>
                
                <Link to="/login">点击跳转到登陆页面</Link>
                <br/>
                <Link to="/home">点击跳转到主页面</Link>
                
            </div> 
        );
    
    
    • 效果

  • 若要加一个按钮,要用JS API的跳转方法

    则不能用函数式组件,因为函数式组件没有状态

    要换成有状态组件

    有状态组件能取到this作用域,无状态组件取不到

    import React from 'react'
    import  Link  from 'react-router-dom'
    import withRouter from 'react-router-dom'
    import './app.scss'
    import  Button  from 'antd'
    import 'antd/dist/antd.css'
    
    export default class App extends React.Component 
        
        handleJump = () => 
            this.props.history.push('/login');
        
        
        render() 
            return (
                <div className="container">
                    <h1>欢迎来到React小课堂</h1>
                    <Link to="/login">点击此处跳转到登陆页面</Link>
                    <br />
                    <Link to="/home">点击此处跳转到主页面</Link>
                    <br />
                    <Button onClick=this.handleJump>点击跳转到login</Button>
                </div>);
        
    
    

    编译后的warning

    GitHub上有人提过:Failed to parse source map: ‘webpack://antd/./components/config-provider/style/index.less’ URL is not supported #33327

    应该问题不大

    • 问题比较大的是,我点击新建的那个Button会报这个错误

      在StackOverflow上看了解答

      于是我就改成了:

      import React from 'react'
      import  Link  from 'react-router-dom'
      import withRouter from 'react-router-dom'
      import './app.scss'
      import  Button  from 'antd'
      import 'antd/dist/antd.css'
      
      class App extends React.Component 
          
          handleJump = () => 
              this.props.history.push('/login');
          
          
          render() 
              return (
                  <div className="container">
                      <h1>欢迎来到React小课堂</h1>
                      <Link to="/login">点击此处跳转到登陆页面</Link>
                      <br />
                      <Link to="/home">点击此处跳转到主页面</Link>
                      <br />
                      <Button onClick=this.handleJump>点击跳转到login</Button>
                  </div>);
          
      
      export default withRouter(App);
      

      结果直接报这个错了

      又去StackOverflow上面查,查到这个withRouter’ is not exported from 'react-router-dom

      package.json里面看了一下,确实可能是版本问题

          "react-dom": "^17.0.2",
          "react-router-dom": "^6.2.1",
      
      • 结果错误更多了…有5个errors

摆烂
  • 上面那个错误不解决了…

二.路由动态配置

动态路由 路由地址不固定

/detail/2020

  • 前面那波downgrade react-router-dom好像还导致sass和antd丢失了???

    报错module “sass” could not be found ,然后还有Module not found: Error: Can't resolve 'antd/dist/antd.css'

  • 解决办法:

    npm install sass
    npm install antd
    
  • 新增一个详情页 Detail

    新建detail.js

    import React from 'react'
    
    export default function Detail() 
        return (
            <div>
                this is Detail
            </div>);
    
    
  • 修改Router.js

    import  BrowserRouter, Route ,Routes  from "react-router-dom";
    //重命名为Router,Route
    import React from "react"
    import App from "./pages/app"
    import Login from "./pages/login"
    import Home from "./pages/home"
    import Detail from "./pages/detail";
    export default function IRouter() 
        return (
        <BrowserRouter>
            <Routes>
            /* //子路由 */
                <Route path="/" element=<App/>/>
                <Route path="/login" element=<Login/>/>
                <Route path="/home" element=<Home/>/>
                <Route path="/detail/:id" element=<Detail/>></Route>
                
                </Routes>
        </BrowserRouter> );
               
    
    
    

    关于代码中的:id,可以看react router path 中通配符

Redirect/404

  • 视频里的Redirect 在 react-router-dom v6版本不支持了

    参考:StackOverflow React: ‘Redirect’ is not exported from ‘react-router-dom’

  • 新建404.js

    import React from 'react'
    
    export default function NoMatch() 
        return <div style=color:'red'>404 Not Found!</div>
    
    
  • 修改router.js

    import  BrowserRouter, Route ,Routes  from "react-router-dom";
    //重命名为Router,Route
    import  Navigate  from "react-router-dom"
    import React from "react"
    import App from "./pages/app"
    import Login from "./pages/login"
    import Home from "./pages/home"
    import Detail from "./pages/detail";
    import NoMatch from "./pages/404"
    export default function IRouter() 
        return (
        <BrowserRouter>
            <Routes>
            /* //子路由 */
                <Route path="/" element=<App/>/>
                <Route path="/login" element=<Login/>/>
                <Route path="/home" element=<Home/>/>
                <Route path="/detail/:id" element=<Detail/>/>
                <Route path="*" element=<Navigate to="/login"/>/>
                <Route path="*" element=<NoMatch />/>
                </Routes>
                 /* <Navigate to="/404"/>
                  */
        </BrowserRouter> );
               
    
    
    

JS中路由跳转

  • 摆烂

    this.props.history.push实现…但是那个报错我没解决

三.Hook

Hook 是 React 16.8 的新增特性。它可以让你在不编写 class 的情况下使用 state 以及其他的 React 特性。

class组件具备状态和生命周期

hooks可以解决函数式组件没有状态和生命周期的问题

React Hooks

useState

类似于class组件的this.setState
实现函数式组件状态的改变和更新

  • useState就是一个Hook

    在函数式组件调用useState来给组件添加一些内部state

    React会在重复渲染时保留这个state

    useState会返回一对值 : 当前状态 和 一个更新它的函数

    useState唯一的参数是初试state

  • 来个计数器

    app.js:

    import React from 'react';
    import  useState  from 'react';
    import  Link  from 'react-router-dom';
    import  Button  from 'antd'
    import './app.scss'
    import 'antd/dist/antd.css';
    export default function App() 
        //声明一个新的叫做count 的 state 变量
        const [count, setCount] = useState(10);
        return <div className="container">
    
            <h1>哈哈</h1>
            <Link to="/login">点击跳转到登陆页面</Link>
            <br />
            <Link to="/home">点击跳转到主页面</Link>
            <br />
            <p>
                当前count次数 :count
            </p>
            <Button onClick=()=>setCount(count+1)>更新次数</Button>
        </div>
    
    

    原先次数是10 , 点击之后更新

useEffect

解决函数式组件的生命是周期

路由Hooks

useParams

获取参数

  • 修改detail.js

    import React from 'react'
    import  Link, useParams  from 'react-router-dom'
    
    export default function Detail() 
        const params = useParams();
        return <div className="container">
            this is detail.
            JSON.stringify(params)
        </div>
    
    
  • router.js如下

    import  BrowserRouter, Route ,Routes  from "react-router-dom";
    //重命名为Router,Route
    import  Navigate  from "react-router-dom"
    import React from "react"
    import App from "./pages/app"
    import Login from "./pages/login"
    import Home from "./pages/home"
    import Detail from "./pages/detail";
    import NoMatch from "./pages/404"
    export default function IRouter() 
        return (
        <BrowserRouter>
            <Routes>
            /* //子路由 */
                <Route path="/" element=<App/>/>
                <Route path="/login" element=<Login/>/>
                <Route path="/home" element=<Home/>/>
                <Route path="/detail/:id" element=<Detail/>/>
               
                </Routes>
               
        </BrowserRouter> );
               
    
    
    

进入localhost:3000/detail/1618,效果如下:

useNavigate

路由跳转

相当于class组件的this.props.history.push

视频里的useHistory更新为useNavigate了

  • 代码

    detail.js

    import React from 'react'
    import  Link, useParams,useNavigate  from 'react-router-dom'
    import  Button  from 'antd'
    import 'antd/dist/antd.css';
    export default function Detail() 
        const params = useParams();
        const navigate = useNavigate();
        return <div className="container">
            <Button>this is detail. </Button>
            
            /* JSON.stringify(params) */
            <p>当前参数值:params.id</p>
            <Button onClick=() => navigate('/home') type="primary">跳转到首页</Button>  
            
        </div>
    
    
  • 效果

    能实现跳转

以上是关于React入门4的主要内容,如果未能解决你的问题,请参考以下文章

React入门4

React入门4

React Router 4.0中文快速入门

大地经纬度坐标与地心地固坐标的的转换

react入门----基础语法

react入门----事件监听