1.ReactRouter
- reactRouter官网地址:reactrouter.com/en/main
- reactRouter安装:npm install react-router-dom
- reactRouter有两种模式:
history模式:createBrowseRouter和hash模式:createHashRouter - 配置路由表:
[{path,element,children}] - 声明书写法:
<Route path='' element={}/> - 路由生效组件:
<RouterProvider router={router}/> - 路由区域显示组件,相当于VueRouter的router-view
2.hooks理解
1.useState
作用:用于为函数组件引入状态(state)。纯函数不能有状态,所以把状态放在勾子里面。第一个参数设置为初始值,第二个参数用于修改更新.
import React,{useSate} from 'react'
const [statenum,setstateNum]=React.useState(0)
2.useEffect 作用引入具有副作用的操作,就是指定一个副效应函数,组件每渲染一次,该函数就自动执行一次。 组件首次在网页DOM加载后,副效应函数也会执行。(用于模拟类组件中的生命周期钩子),最常见的就是向服务器请求数据。以前,放在类组件compoentDidMount钩子中,函数组件就可以放在useEffect()。 使用方式
useEffect(()=>{
},[dependencies])
1.useEffect的依赖项为[]时,模拟类组件生命周期的componendDidMount(组件挂载完成后)。
useEffect(()=>{
//z在组件渲染完成后执行的副作用操作
fetchData()
},[])
const fetchData = async () => {
// 异步获取数据的逻辑
const response = await fetch('https://api.example.com/data');
const json = await response.json();
setData(json);
};
- useEffect的依赖项为[data]时,模拟类组件生命周期的componentDidUpdate,只要其中任何一个state改变,就会重新渲染
const [varA, setVarA] = useState(0);
useEffect(() => {
const timeout = setTimeout(() => setVarA(varA + 1), 1000);
return () => clearTimeout(timeout);
}, [varA]);
- 如果没有第二个数据,只有一个函数,模拟类组件的销毁时期
useEffect(() => {
const subscription = props.source.subscribe();
return () => {
subscription.unsubscribe();
};
}, [props.source]);
3.react状态管理 3.1 Redux状态管理
- 旧版Redux使用createStore管理状态
- 使用dispatch传递的参数会到action
//store/index.js
import {createsStore} from 'redux'
const countReducer =(state={count:0},action)=>{
//返回新的state
switch(action.type){
case 'inc':
return {count: state.count + action.payload}
default:
return state
}
}
const store=createStore(countReducer)
export default store
- 使用subscribe()检测状态的变化
- 需要使用useState()修改状态
//在Footer组件中
import React from 'react'
import store from '../../store'
import './Footer.scss'
export default function Footer(){
const [count,setCount]=React.useStore(store.getState().count)
const handleClick=()=>{
store.dispatch({
type:'inc',
payload:5
})
}
store.subscribe(()=>{
setCount(store.getState().count)
})
return (
<div>
<button onClick={handleClick}>修改值</button>
<div>Footer,{count}</div>
</div>
)
}
3.2ReactRedux简化对Redux的使用
<Provider store={store} >
// index.js
import React from 'react';
import ReactDOM from 'react-dom/client';
// import App from './App';
import { Provider } from 'react-redux';
import { RouterProvider } from 'react-router-dom';
import './index.css';
import reportWebVitals from './reportWebVitals';
import router from './router';
import store from './store';
const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(
// React.StrictMode 会导致子组件执行两次
<React.StrictMode>
{/* <App /> */}
<Provider store={store}>
<RouterProvider router={router}> </RouterProvider>
</Provider>
</React.StrictMode>
);
// If you want to start measuring performance in your app, pass a function
// to log results (for example: reportWebVitals(console.log))
// or send to an analytics endpoint. Learn more: https://bit.ly/CRA-vitals
reportWebVitals();
- useSelector
- useDispatch
//在Footer组件使用
import React from 'react'
// import store from '../../store'
import { useDispatch, useSelector } from 'react-redux'
import './Footer.scss'
export default function Footer() {
// const [count, setCount] = React.useState(store.getState().count)
const count = useSelector(state => state.count)
const dispatch = useDispatch()
const handleClick = () => {
// store.dispatch({
// type: 'inc'
// })
dispatch({
type: 'inc'
})
}
// store.subscribe(() => {
// setCount(store.getState().count)
// })
return (
<div>
<button onClick={handleClick}>修改值</button>
<div>Footer, { count }</div>
</div>
)
}
3.3处理多个Reducer函数及Redux模块化
- 使用combineReducers方法处理多个reducer函数
- 模块化时注意添加明名空间
// store/index.js
import { combineReducers, createStore } from 'redux';
import { countReducer } from './modules/counter';
import { messageReducer } from './modules/message';
const store = createStore(combineReducers({
countNameSpace: countReducer,
messageNameSpace: messageReducer
}))
export default store
// store/modules/counter
export const countReducer = (state = { count: 0 }, action) => {
// 返回新的state
switch (action.type) {
case 'inc':
return { count: state.count + action.payload }
default:
return state
}
}
// store/modules/message
export const messageReducer = (state = { msg: 'hello' }, action) => {
// 返回新的state
switch (action.type) {
case 'change':
return { msg: action.payload }
default:
return state
}
}
// Footer.jsx
import React from 'react'
// import store from '../../store'
import { useDispatch, useSelector } from 'react-redux'
import './Footer.scss'
export default function Footer() {
// const [count, setCount] = React.useState(store.getState().count)
const count = useSelector(state => state.countNameSpace.count)
const message = useSelector(state => state.messageNameSpace.msg)
const dispatch = useDispatch()
const handleClick = () => {
// store.dispatch({
// type: 'inc'
// })
dispatch({
type: 'inc',
payload: 5
})
dispatch({
type: 'change',
payload: 'hello world'
})
}
// store.subscribe(() => {
// setCount(store.getState().count)
// })
return (
<div>
<button onClick={handleClick}>修改值</button>
<div>Footer, { count }, {message}</div>
</div>
)
}
3.4Redux-Thunk中间件处理异步操作
- dispatch默认只支持对面字面量,通过redux-thunk可以让dispatch支持回调函数
- 通过applyMiddleware方法,让中间间生效
- 安装redux-thunk
import { applyMiddleware, combineReducers, createStore } from 'redux';
import thunk from 'redux-thunk';
import { countReducer } from './modules/counter';
import { messageReducer } from './modules/message';
// 多个中间件可以 applyMiddleware(thunk, xxx, xxx ....)
const store = createStore(combineReducers({
countNameSpace: countReducer,
messageNameSpace: messageReducer
}), applyMiddleware(thunk))
export default store
// Footer.jsx
import React from 'react'
// import store from '../../store'
import { useDispatch, useSelector } from 'react-redux'
import './Footer.scss'
export default function Footer() {
// const [count, setCount] = React.useState(store.getState().count)
const count = useSelector(state => state.countNameSpace.count)
const message = useSelector(state => state.messageNameSpace.msg)
const dispatch = useDispatch()
const handleClick = () => {
// store.dispatch({
// type: 'inc'
// })
// dispatch({
// type: 'inc',
// payload: 5
// })
// dispatch({
// type: 'change',
// payload: 'hello world'
// })
// 使用 ReduxThunk 后支持回调函数
dispatch((dispatch) => {
setTimeout(() => {
dispatch({
type: 'inc',
payload: 5
})
dispatch({
type: 'change',
payload: 'hello world'
})
},5000)
})
}
// store.subscribe(() => {
// setCount(store.getState().count)
// })
return (
<div>
<button onClick={handleClick}>修改值</button>
<div>Footer, { count }, {message}</div>
</div>
)
}
3.5Redux-Toolkit(RTK)改善Redux使用体验
- 可以自动跟redux devtools结合,不需要再下载相应的模块
- 数据不需要再通过返回值进行修改,像vue一样可以直接修改
- 内置了ReduxThunk这个异步插件
- 代码风格更好,采用选项式编程
- 安装redux-toolKit
Redux-Toolkit 模块:
- name::触发 dispatch 的命名空间
- initialState:初始化共享状态
- reducers:编写 reducer 方法