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>);
参考:
试着按照弹幕改了改,但报了这个错
嘿嘿 这段时间学了英语,终于能耐心地去看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
应该问题不大
-
问题比较大的是,我点击新建的那个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> );
- segmentfault:react-router-dom v6 移除Redirect后的解决方案
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的主要内容,如果未能解决你的问题,请参考以下文章