diff --git a/practise/31.hook/01.useState的基础使用.jsx b/practise/31.hook/01.useState的基础使用.jsx
new file mode 100644
index 0000000..1bc3408
--- /dev/null
+++ b/practise/31.hook/01.useState的基础使用.jsx
@@ -0,0 +1,40 @@
+/* useState
+1.导入 useState 函数 (从 react 导入)
+2.执行这个函数并且传入初始值,必须在函数组件中
+3.解构: [数据,修改数据的方法]
+4.使用数据 修改数据 */
+
+/* 状态的读取和修改
+ const [count, setCount] = useState(0)
+1.useState 传过来的参数作为 count 的初始值
+2. [count, setCount] 这里的写法是一个解构赋值,useState 返回值是一个数组
+3. [] 里面的值名字可以自定义,保持语义化
+4. [] 里面的值顺序不能更换,第一个参数是数据状态,第二参数是修改数据的方法
+5. setCount 函数作用用来修改 count, 依旧保持不能直接修改原值,要生成一个新值替换原值。setCount(基于原值计算得到的新值)
+6. count 和 setCount 是一对的,绑定在一起的,setCount 只能用来修改对应的 count 值 */
+
+/* 组件的更新
+当调用 setCount 的时候,更新过程:
+
+首次渲染:
+首次被渲染的时候,组件的内部代码会被执行一次,其中 useState 也会跟着执行,重点注意:初始值只在首次渲染是生效
+
+更新渲染 setCount 都会更新
+1. app 组件会再次渲染,这个函数会再次执行
+2. useState 再次执行,得到的新的 count 值不是 0 ,而是修改之后的 1,模板会用新值渲染
+
+重点:useState 初始值只在首次渲染生效,后续只要调用 setCount,整个 app 中代码都会执行,此时的 count 每次拿到的都是最新值
+*/
+
+import { useState } from 'react'
+
+function App () {
+ const [count, setCount] = useState(0) // 0 是初始值
+ return (
+
+
+
+ )
+}
+
+export default App
diff --git a/practise/31.hook/02.useState的使用2.jsx b/practise/31.hook/02.useState的使用2.jsx
new file mode 100644
index 0000000..723304c
--- /dev/null
+++ b/practise/31.hook/02.useState的使用2.jsx
@@ -0,0 +1,27 @@
+import { useState } from 'react'
+
+/* useState 注意事项 :
+1.只能出现在函数组件中
+2.不能嵌套在if/for/其它函数中(react按照hooks的调用顺序识别每一个hook) */
+
+function App () {
+ const [count, setCount] = useState(0) // 0 是 count 的初始值
+ const [flag, setFlag] = useState(true) // true 是 flag 的初始值
+ const [list, setList] = useState([]) // [] 是 list 的初始值,是一个空数组
+
+ function test () {
+ setCount(count + 1)
+ setFlag(false)
+ setList([1, 2, 3])
+ }
+
+ return (
+
+ count: {count}
+ flag: {flag ? '1' : '0'}
+ list: {list.join('-')}
+
+ )
+}
+
+export default App
diff --git a/practise/31.hook/03.useEffect副作用.jsx b/practise/31.hook/03.useEffect副作用.jsx
new file mode 100644
index 0000000..a8a60b8
--- /dev/null
+++ b/practise/31.hook/03.useEffect副作用.jsx
@@ -0,0 +1,25 @@
+import { useState, useEffect } from 'react'
+
+// useEffect函数,作用就是为 react 函数组件提供副作用处理的
+
+/* 在修改数据之后,把 count 值放在页面标题中
+1.导入 useEffect 函数
+2.在函数组件中执行,传入回调,并且定义副作用
+3.当通过修改状态更新组件时,副作用也会不断执行 */
+
+function App () {
+ const [count, setCount] = useState(0) // 0 是 count 的初始值
+
+ useEffect(() => {
+ // 定义副作用
+ document.title = count
+ })
+
+ return (
+
+
+
+ )
+}
+
+export default App
diff --git a/practise/31.hook/04.useEffect依赖项.jsx b/practise/31.hook/04.useEffect依赖项.jsx
new file mode 100644
index 0000000..8468e41
--- /dev/null
+++ b/practise/31.hook/04.useEffect依赖项.jsx
@@ -0,0 +1,50 @@
+import { useState, useEffect } from 'react'
+
+// useEffect函数,作用就是为 react 函数组件提供副作用处理的
+
+/* 依赖项控制副作用的执行时机
+1.默认状态(无依赖项):组件初始化的时候先执行一次,等到每次数据修改组件更新再次执行
+
+2.添加一个空数组依赖项,组件初始化的时候执行一次
+
+3. 依赖特定项:组件初始化的时候执行一次,依赖的特定项发生变化会再次执行
+
+4.注意事项:只要 useEffect 回调函数中用到的数据状态就应该出现在依赖项数组中声明,否侧可能会有 bug
+
+hook 的出现就是在不用生命周期的概念也可以写业务代码
+*/
+
+
+function App() {
+ const [count, setCount] = useState(0) // 0 是 count 的初始值
+ const [name, setName] = useState('one')
+
+ /* useEffect(() => {
+ // 定义副作用
+ console.log('副作用又执行了')
+ document.title = count
+ }, []) */ // 添加一个空数组依赖项 [],组件只在首次渲染时执行一次
+
+ /* useEffect(() => {
+ // 定义副作用
+ console.log('副作用又执行了')
+ document.title = count
+ }, [count]) */ // 添加特定依赖项 [count]
+
+ // 初始化 + count 或 name 被修改时都会执行副作用函数
+ useEffect(() => {
+ // 定义副作用
+ console.log('副作用又执行了')
+ document.title = count
+ console.log(name)
+ }, [count,name])
+
+ return (
+
+
+
+
+ )
+}
+
+export default App
diff --git a/practise/31.hook/05.useState 函数作为参数.jsx b/practise/31.hook/05.useState 函数作为参数.jsx
new file mode 100644
index 0000000..fb5c2c4
--- /dev/null
+++ b/practise/31.hook/05.useState 函数作为参数.jsx
@@ -0,0 +1,34 @@
+import { useState } from 'react'
+
+function getDefaultValue () {
+ for (let i = 0; i < 10000; i++) {
+ }
+ return '10'
+}
+
+function Counter (props) {
+ const [count, setCount] = useState(() => {
+ /**
+ * 初始值经过一定的计算:
+ * 只要无法直接确定,需要通过一定的操作才能获取,就可以理解为计算
+ */
+ // return props.count
+
+ // 循环遍历一万条数据才能确定这里的初始值
+ return getDefaultValue()
+ })
+ return (
+
+ )
+}
+
+function App () {
+ return (
+
+
+
+
+ )
+}
+
+export default App
\ No newline at end of file
diff --git a/practise/31.hook/06.useEffect 清除副作用.jsx b/practise/31.hook/06.useEffect 清除副作用.jsx
new file mode 100644
index 0000000..be2fa3b
--- /dev/null
+++ b/practise/31.hook/06.useEffect 清除副作用.jsx
@@ -0,0 +1,30 @@
+import { useEffect, useState } from 'react'
+
+function Test () {
+ useEffect(() => {
+ let timer = setInterval(() => {
+ console.log('定时器执行了')
+ }, 1000)
+
+ return () => {
+ // 清理定时器
+ clearInterval(timer)
+ }
+ }, [])
+
+ return (
+ this is test
+ )
+}
+
+function App () {
+ const [flag, setFlag] = useState(true)
+ return (
+
+ {flag ? : null}
+
+
+ )
+}
+
+export default App
\ No newline at end of file
diff --git a/practise/31.hook/07.useEffect 发送网络请求.jsx b/practise/31.hook/07.useEffect 发送网络请求.jsx
new file mode 100644
index 0000000..0ae22bf
--- /dev/null
+++ b/practise/31.hook/07.useEffect 发送网络请求.jsx
@@ -0,0 +1,30 @@
+/**
+ * 类组件发送网络请求:
+ * 生命周期钩子函数:componentDidMount;执行时机:在初始化的时候 dom 渲染完毕时只执行一次
+ */
+
+/**
+ * 1.不加依赖项,执行时机:初始化 + 重新渲染
+ * 2.加 [] , 执行时机:初始化执行一次
+ * 3.加特定的依赖项 [count, name] ,执行时机:首次执行 + 任意一个变化执行
+ */
+
+ import { useEffect } from 'react'
+
+ function App () {
+ useEffect(() => {
+ // 发送请求
+ async function loadData () {
+ const res = await fetch('http://geek.itheima.net/v1_0/channels')
+ console.log(res)
+ }
+ loadData()
+ }, [])
+
+ return (
+
+
+ )
+ }
+
+ export default App
\ No newline at end of file
diff --git a/practise/31.hook/08.useRef的使用.jsx b/practise/31.hook/08.useRef的使用.jsx
new file mode 100644
index 0000000..169bb1c
--- /dev/null
+++ b/practise/31.hook/08.useRef的使用.jsx
@@ -0,0 +1,45 @@
+import React, { useEffect, useRef } from 'react'
+
+// useRef:在函数组件中获取真实的dom元素对象或者是组件对象
+/**
+ * 使用步骤
+ * 1. 导入 useRef 函数
+ * 2. 执行 useRef 函数并传入null,返回值为一个对象 内部有一个current属性存放拿到的dom对象(类组件实例)
+ * 3. 通过ref 绑定 要获取的元素或者组件
+ */
+
+class TestC extends React.Component {
+ state = {
+ name: 'Ken'
+ }
+
+ getName = () => {
+ return 'this is child Test'
+ }
+
+ render () {
+ return (
+ 类组件
+ )
+ }
+}
+
+function App () {
+ const testRef = useRef(null)
+ const h1Ref = useRef(null)
+
+ // useEffect 回调是在 dom 渲染之后的。和 vue 里的 watch 效果较像,但是执行时机是不同的
+ useEffect(() => {
+ console.log(testRef.current)
+ console.log(h1Ref.current)
+ }, [])
+
+ return (
+
+
+ this is h1
+
+ )
+}
+
+export default App
\ No newline at end of file
diff --git a/practise/31.hook/09.useContext使用.jsx b/practise/31.hook/09.useContext使用.jsx
new file mode 100644
index 0000000..64b1374
--- /dev/null
+++ b/practise/31.hook/09.useContext使用.jsx
@@ -0,0 +1,44 @@
+import React, { createContext, useContext, useState } from 'react'
+
+// 1.创建 Context 对象,调用 createContext 方法
+const Context = createContext()
+
+function ComA() {
+ const count = useContext(Context)
+ return (
+
+ this is ComA
+
+ 传过来的数据为:{count}
+
+
+ )
+}
+
+function ComC() {
+ // 3.底层组件通过 useContext 函数获取数据
+ const count = useContext(Context)
+ return (
+
+ this is ComC
+
+ 传过来的数据为:{count}
+
+ )
+}
+
+function App() {
+ const [ count, setCount ] = useState(0)
+
+ return (
+ // 2.顶层组件通过 Context.Provider 提供数据
+
+
+
+
+
+
+ )
+}
+
+export default App
\ No newline at end of file
diff --git a/practise/31.hook/hook阶段小练习/01/index.js b/practise/31.hook/hook阶段小练习/01/index.js
new file mode 100644
index 0000000..b9b972f
--- /dev/null
+++ b/practise/31.hook/hook阶段小练习/01/index.js
@@ -0,0 +1,14 @@
+import { useWindowScroll } from './useWindowScroll.js'
+
+function App () {
+ const [y] = useWindowScroll()
+
+ return (
+
+ {y}
+ {console.log(y)}
+
+ )
+}
+
+export default App
\ No newline at end of file
diff --git a/practise/31.hook/hook阶段小练习/01/useWindowScroll.js b/practise/31.hook/hook阶段小练习/01/useWindowScroll.js
new file mode 100644
index 0000000..03cb8dd
--- /dev/null
+++ b/practise/31.hook/hook阶段小练习/01/useWindowScroll.js
@@ -0,0 +1,13 @@
+import { useState } from 'react'
+
+
+export function useWindowScroll () {
+ const [y, sety] = useState(0)
+
+ // 在滚动行为发生的时候,不断获取滚动值,然后交给 y
+ window.addEventListener('scroll', () => {
+ const h = document.documentElement.scrollTop // documentElement 属性以一个元素对象返回一个文档的文档元素。
+ sety(h)
+ })
+ return [y]
+}
diff --git a/practise/31.hook/hook阶段小练习/02/index.js b/practise/31.hook/hook阶段小练习/02/index.js
new file mode 100644
index 0000000..36a8c06
--- /dev/null
+++ b/practise/31.hook/hook阶段小练习/02/index.js
@@ -0,0 +1,15 @@
+import { useLocalStorage } from './useLocalStorage'
+
+function App () {
+ const [message, setMessage] = useLocalStorage('hook-key', 'ken')
+ setTimeout(() => {
+ setMessage('cp')
+ }, 5000);
+ return (
+
+ {message}
+
+ )
+}
+
+export default App
\ No newline at end of file
diff --git a/practise/31.hook/hook阶段小练习/02/useLocalStorage.js b/practise/31.hook/hook阶段小练习/02/useLocalStorage.js
new file mode 100644
index 0000000..dbf6a08
--- /dev/null
+++ b/practise/31.hook/hook阶段小练习/02/useLocalStorage.js
@@ -0,0 +1,15 @@
+import { useEffect, useState} from 'react'
+
+/* const {message, setMessage} = useState(defaultValue)
+1.message 可以通过自定义传入默认初始值
+2.每次修改 message 数据的时候,都会自动往同步一份 */
+
+export function useLocalStorage (key, defaultValue) {
+ const [message, setMessage] = useState(defaultValue)
+ // 每次只要 message 变化,就会自动同步到本地 localStorage
+ useEffect (() => {
+ // setItem(keyname, value) 是添加键和值,如果对应的值存在,则更新该键对应的值。
+ window.localStorage.setItem(key, message)
+ }, [message, key])
+ return [message, setMessage]
+}
\ No newline at end of file
diff --git a/practise/31.hook/useContext/context.js b/practise/31.hook/useContext/context.js
new file mode 100644
index 0000000..90c6cf7
--- /dev/null
+++ b/practise/31.hook/useContext/context.js
@@ -0,0 +1,13 @@
+/**
+ * 1.调用 createContext 方法
+ * 2.通过顶层组件包裹 Context.Provider
+ * 3.底层组件 useContext (createContext 返回的对象)
+ */
+
+import { createContext } from "react"
+
+const Context = createContext()
+
+export default Context
+
+
diff --git a/practise/31.hook/useContext/index.js b/practise/31.hook/useContext/index.js
new file mode 100644
index 0000000..129cfe7
--- /dev/null
+++ b/practise/31.hook/useContext/index.js
@@ -0,0 +1,43 @@
+import React, { useContext, useState } from 'react'
+
+import Context from './context'
+
+function ComA() {
+ const count = useContext(Context)
+ return (
+
+ this is ComA
+
+ 传过来的数据为:{count}
+
+
+ )
+}
+
+function ComC() {
+ // 3.底层组件通过 useContext 函数获取数据
+ const count = useContext(Context)
+ return (
+
+ this is ComC
+
+ 传过来的数据为:{count}
+
+ )
+}
+
+function App() {
+ const [ count, setCount ] = useState(0)
+
+ return (
+ // 2.顶层组件通过 Context.Provider 提供数据
+
+
+
+
+
+
+ )
+}
+
+export default App
\ No newline at end of file
diff --git a/practise/31.hook/useContext补充.png b/practise/31.hook/useContext补充.png
new file mode 100644
index 0000000..c8d68c8
Binary files /dev/null and b/practise/31.hook/useContext补充.png differ
diff --git a/practise/32.react-router/01.BrowserRouter.jsx b/practise/32.react-router/01.BrowserRouter.jsx
new file mode 100644
index 0000000..dce7e19
--- /dev/null
+++ b/practise/32.react-router/01.BrowserRouter.jsx
@@ -0,0 +1,25 @@
+// 引入两个组件
+import Home from "./Home";
+import About from "./About";
+
+import { BrowserRouter, Link, Routes, Route} from "react-router-dom"
+
+// 进行路由配置
+function App() {
+ return (
+ // BrowserRouter 是声明当前要用一个非 hash 模式的路由
+
+ {/* Link 是指定跳转的组件,to 用来配置路由地址 */}
+ 首页
+ 关于
+ {/* Routes 是路由出口,路由对应的组件会在这里进行渲染 */}
+
+ {/* Route 是指定路径和组件的对应关系,path 代表路径,element 代表组件,两个是成对出现的,一个 path 对应一个 element */}
+ }>
+ }>
+
+
+ );
+}
+
+export default App;
diff --git a/practise/32.react-router/02.编程式导航-实现跳转/Login.js b/practise/32.react-router/02.编程式导航-实现跳转/Login.js
new file mode 100644
index 0000000..0629c24
--- /dev/null
+++ b/practise/32.react-router/02.编程式导航-实现跳转/Login.js
@@ -0,0 +1,21 @@
+// 1.导入 useNavigate
+import { useNavigate } from 'react-router-dom'
+
+function Login() {
+ // 2.执行 useNavigate 得到一个跳转函数
+ const navigate = useNavigate()
+
+ function goAbout() {
+ // 3.调用跳转函数传入目标路径,{replace: true} 是在跳转时不加入历史记录,不能跳转回登录页
+ navigate('/about', {replace: true})
+ }
+
+ return (
+
+ Login
+
+
+ )
+}
+
+export default Login
\ No newline at end of file
diff --git a/practise/32.react-router/02.编程式导航-实现跳转/index.js b/practise/32.react-router/02.编程式导航-实现跳转/index.js
new file mode 100644
index 0000000..17e90e1
--- /dev/null
+++ b/practise/32.react-router/02.编程式导航-实现跳转/index.js
@@ -0,0 +1,28 @@
+// 引入两个组件
+import Home from "./Home";
+import About from "./About";
+import Login from "./Login";
+
+import { BrowserRouter, Link, Routes, Route} from "react-router-dom"
+
+// 进行路由配置
+function App() {
+ return (
+ // BrowserRouter 是声明当前要用一个非 hash 模式的路由
+
+ {/* Link 是指定跳转的组件,to 用来配置路由地址 */}
+ 首页
+ 关于
+ {/* 登录 */}
+ {/* Routes 是路由出口,路由对应的组件会在这里进行渲染 */}
+
+ {/* Route 是指定路径和组件的对应关系,path 代表路径,element 代表组件,两个是成对出现的,一个 path 对应一个 element */}
+ }>
+ }>
+ }>
+
+
+ );
+}
+
+export default App;
diff --git a/practise/32.react-router/03.跳转传参-searchParams/About.js b/practise/32.react-router/03.跳转传参-searchParams/About.js
new file mode 100644
index 0000000..14e47dd
--- /dev/null
+++ b/practise/32.react-router/03.跳转传参-searchParams/About.js
@@ -0,0 +1,17 @@
+import { useSearchParams } from 'react-router-dom'
+
+function About () {
+ const [params] = useSearchParams()
+
+ /**
+ * params 是一个对象,对象里有一个 get 的方法,用来获取对应的参数,把参数的名称作为 get 方法的实参传过来
+ */
+
+ const id = params.get('id')
+
+ return (
+ About得到的参数 id 值为 {id}
+ )
+}
+
+export default About
\ No newline at end of file
diff --git a/practise/32.react-router/03.跳转传参-searchParams/Login.js b/practise/32.react-router/03.跳转传参-searchParams/Login.js
new file mode 100644
index 0000000..255828e
--- /dev/null
+++ b/practise/32.react-router/03.跳转传参-searchParams/Login.js
@@ -0,0 +1,21 @@
+// 1.导入 useNavigate
+import { useNavigate } from 'react-router-dom'
+
+function Login() {
+ // 2.执行 useNavigate 得到一个跳转函数
+ const navigate = useNavigate()
+
+ function goAbout() {
+ // 3.调用跳转函数传入目标路径,{replace: true} 是在跳转时不加入历史记录,不能跳转回登录页
+ navigate('/about?id=1001', {replace: true})
+ }
+
+ return (
+
+ Login
+
+
+ )
+}
+
+export default Login
\ No newline at end of file
diff --git a/practise/32.react-router/04.跳转传参-params/About.js b/practise/32.react-router/04.跳转传参-params/About.js
new file mode 100644
index 0000000..c350136
--- /dev/null
+++ b/practise/32.react-router/04.跳转传参-params/About.js
@@ -0,0 +1,15 @@
+// 使用 params 传参。还需要在 App.js 的传参路径 path 添加 /:id
+// 例如:}>
+
+import { useParams } from 'react-router-dom'
+
+function About () {
+
+ const params = useParams()
+
+ return (
+ About得到的参数 id 值为 {params.id}
+ )
+}
+
+export default About
\ No newline at end of file
diff --git a/practise/32.react-router/04.跳转传参-params/Login.js b/practise/32.react-router/04.跳转传参-params/Login.js
new file mode 100644
index 0000000..563eda1
--- /dev/null
+++ b/practise/32.react-router/04.跳转传参-params/Login.js
@@ -0,0 +1,21 @@
+// 1.导入 useNavigate
+import { useNavigate } from 'react-router-dom'
+
+function Login() {
+ // 2.执行 useNavigate 得到一个跳转函数
+ const navigate = useNavigate()
+
+ function goAbout() {
+ // 3.调用跳转函数传入目标路径,{replace: true} 是在跳转时不加入历史记录,不能跳转回登录页
+ navigate('/about/1001', {replace: true})
+ }
+
+ return (
+
+ Login
+
+
+ )
+}
+
+export default Login
\ No newline at end of file
diff --git a/practise/32.react-router/05.嵌套路由/Article.js b/practise/32.react-router/05.嵌套路由/Article.js
new file mode 100644
index 0000000..f301f89
--- /dev/null
+++ b/practise/32.react-router/05.嵌套路由/Article.js
@@ -0,0 +1,7 @@
+function Article () {
+ return (
+ Article
+ )
+}
+
+export default Article
\ No newline at end of file
diff --git a/practise/32.react-router/05.嵌套路由/Board.js b/practise/32.react-router/05.嵌套路由/Board.js
new file mode 100644
index 0000000..6d76ba6
--- /dev/null
+++ b/practise/32.react-router/05.嵌套路由/Board.js
@@ -0,0 +1,7 @@
+function Board () {
+ return (
+ Board
+ )
+}
+
+export default Board
\ No newline at end of file
diff --git a/practise/32.react-router/05.嵌套路由/Layout.js b/practise/32.react-router/05.嵌套路由/Layout.js
new file mode 100644
index 0000000..9d53a12
--- /dev/null
+++ b/practise/32.react-router/05.嵌套路由/Layout.js
@@ -0,0 +1,12 @@
+import { Outlet } from 'react-router-dom'
+
+function Layout () {
+ return (
+
+ Layout
+
+
+ )
+}
+
+export default Layout
\ No newline at end of file
diff --git a/practise/32.react-router/05.嵌套路由/Login.js b/practise/32.react-router/05.嵌套路由/Login.js
new file mode 100644
index 0000000..f3aaf1d
--- /dev/null
+++ b/practise/32.react-router/05.嵌套路由/Login.js
@@ -0,0 +1,10 @@
+function Login() {
+
+ return (
+
+ Login
+
+ )
+}
+
+export default Login
\ No newline at end of file
diff --git a/practise/32.react-router/05.嵌套路由/index.js b/practise/32.react-router/05.嵌套路由/index.js
new file mode 100644
index 0000000..5c42910
--- /dev/null
+++ b/practise/32.react-router/05.嵌套路由/index.js
@@ -0,0 +1,29 @@
+// 引入两个组件
+import Login from "./Login";
+import Layout from "./Layout";
+import Board from "./Board";
+import Article from "./Article";
+
+import { BrowserRouter, Routes, Route} from "react-router-dom"
+
+// 进行路由配置
+function App() {
+ return (
+
+
+
+
+
+ }>
+ {/* 定义二级路由嵌套 */}
+ }>
+ }>
+
+
+ }>
+
+
+ );
+}
+
+export default App;
diff --git a/practise/32.react-router/06.默认二级路由设置.jsx b/practise/32.react-router/06.默认二级路由设置.jsx
new file mode 100644
index 0000000..99060af
--- /dev/null
+++ b/practise/32.react-router/06.默认二级路由设置.jsx
@@ -0,0 +1,30 @@
+// 引入两个组件
+import Login from "./Login";
+import Layout from "./Layout";
+import Board from "./Board";
+import Article from "./Article";
+
+import { BrowserRouter, Routes, Route} from "react-router-dom"
+
+// 进行路由配置
+function App() {
+ return (
+
+
+
+
+
+ }>
+ {/* 定义二级路由嵌套 */}
+ {/* 进入页面指定显示:默认二级,添加 index 属性,将自己的 path 干掉 */}
+ }>
+ }>
+
+
+ }>
+
+
+ );
+}
+
+export default App;
diff --git a/practise/32.react-router/07.404页配置/NotFound.js b/practise/32.react-router/07.404页配置/NotFound.js
new file mode 100644
index 0000000..aa403a3
--- /dev/null
+++ b/practise/32.react-router/07.404页配置/NotFound.js
@@ -0,0 +1,9 @@
+function NotFound () {
+ return (
+
+ sorry,this page is lost
+
+ )
+}
+
+export default NotFound
\ No newline at end of file
diff --git a/practise/32.react-router/07.404页配置/index.js b/practise/32.react-router/07.404页配置/index.js
new file mode 100644
index 0000000..9571eb6
--- /dev/null
+++ b/practise/32.react-router/07.404页配置/index.js
@@ -0,0 +1,30 @@
+// 引入两个组件
+import Layout from "./Layout";
+import Board from "./Board";
+import Article from "./Article";
+import NotFound from "./NotFound";
+
+import { BrowserRouter, Routes, Route} from "react-router-dom"
+
+// 进行路由配置
+function App() {
+ return (
+
+
+
+
+
+ }>
+ {/* 定义二级路由嵌套 */}
+ }>
+ }>
+
+
+ {/* 当所有的路径都没有匹配时,做兜底匹配,显示未找到 */}
+ }>
+
+
+ );
+}
+
+export default App;
diff --git a/practise/32.react-router/picture/1.png b/practise/32.react-router/picture/1.png
new file mode 100644
index 0000000..27bfb94
Binary files /dev/null and b/practise/32.react-router/picture/1.png differ
diff --git a/practise/32.react-router/picture/2.png b/practise/32.react-router/picture/2.png
new file mode 100644
index 0000000..33a30f9
Binary files /dev/null and b/practise/32.react-router/picture/2.png differ
diff --git a/practise/32.react-router/picture/3.png b/practise/32.react-router/picture/3.png
new file mode 100644
index 0000000..1db86dc
Binary files /dev/null and b/practise/32.react-router/picture/3.png differ
diff --git a/practise/32.react-router/picture/4.png b/practise/32.react-router/picture/4.png
new file mode 100644
index 0000000..8911d4d
Binary files /dev/null and b/practise/32.react-router/picture/4.png differ
diff --git a/practise/32.react-router/picture/5.编程式导航.png b/practise/32.react-router/picture/5.编程式导航.png
new file mode 100644
index 0000000..bee4877
Binary files /dev/null and b/practise/32.react-router/picture/5.编程式导航.png differ
diff --git a/practise/32.react-router/picture/6.跳转传参.png b/practise/32.react-router/picture/6.跳转传参.png
new file mode 100644
index 0000000..c257fae
Binary files /dev/null and b/practise/32.react-router/picture/6.跳转传参.png differ
diff --git a/practise/32.react-router/picture/7.嵌套路由.png b/practise/32.react-router/picture/7.嵌套路由.png
new file mode 100644
index 0000000..cbe79bb
Binary files /dev/null and b/practise/32.react-router/picture/7.嵌套路由.png differ
diff --git a/practise/32.react-router/picture/8.404路由配置.png b/practise/32.react-router/picture/8.404路由配置.png
new file mode 100644
index 0000000..6b6d490
Binary files /dev/null and b/practise/32.react-router/picture/8.404路由配置.png differ