BrowserRouter: 根节点
Routes: 路由配置放在这个标签里面
Route: 配置路由组件的路径和要显示的组件
<Route path='' element=''>
<Route index element=''>
Link: 导航组件
<Link to=''></Link>
NavLink: 导航组件,路由被激活的时候自动添加active类名
<NavLink to=''></NavLink>
Navigate: 导航组件,重定向
<Navigate to=''/>
Outlet: 路由视图组件,当前路由匹配以后显示组件的地方
给需要登录的组件放在同一个父路由中进行鉴权
isLogin?<Outlet>:null
useParams
<Route path='/chat/:id/:from' element=''>
const params = useParams()
params = {id:xxx,from:xxx}
useNavigate
const navigate = useNavigate()
navigate()
useSearchParams
http://xxxxx?a=1&b=2
const [searchParams,setSearchParams] = useSearchParams()
searchParams.get('a');// 1
searchParams.get('b');// 2
setSearchParams({a:23,b:45});// 不能写在外面
useLocation
const location = useLocation()
{path:'',search:'',hash:'',...}
状态管理工具
还有: vuex,mobx,...
state:驱动应用的真实数据源头
view: 基于当前状态的ui声明式描述
actons: 根据用户输入在应用程序中发生的事情,触发状态的更新
store.js
// 导入redux里面的创建仓库的方法 import {createStore} from 'redux'; // 定义state的初始值 const initState = { num:10, age:200 } // 书写一个关联state和actions的函数 // 这个函数就做reducer const store = createStore((state=initState,actions)=>{ switch(actions.type){ case 'addNum': // 生成一个新的state return {...state,num:state.num+actions.payload}; case 'cutNum': // 生成一个新的state return {...state,num:state.num-1}; case 'addAge': // 生成一个新的state return {...state,age:state.age+10}; case 'cutAge': // 生成一个新的state return {...state,age:state.age-10} default: // 生成一个新的state return {...state} } }) // store三个重要方法 // store.dispatch(action) // store.getState() // store.subscribe(listener) export default store;
index.js
import React from 'react'; import ReactDOM from 'react-dom/client'; import App from './App'; import Main from './Main' import reportWebVitals from './reportWebVitals'; const root = ReactDOM.createRoot(document.getElementById('root')); root.render( <> <App /> <hr/> <Main/> </> ); reportWebVitals();
App.js
import store from './store' import {useEffect,useState} from 'react' function App() { // store.getState 获取最新的状态 const [num,setNum] = useState(store.getState().num) const [age,setAge] = useState(store.getState().age) // 订阅更新 useEffect(()=>{ store.subscribe(()=>{ setNum(store.getState().num) setAge(store.getState().age) }) },[]) const add = ()=>{ store.dispatch({type:'addAge'}) } const cut = ()=>{ store.dispatch({type:'cutNum'}) } return ( <div className="App"> <h1>学习redux</h1> <hr/> <h3>数量:{num}-年龄:{age}</h3> <button onClick={add}>点击增加年龄</button> <button onClick={cut}>点击减少数量</button> </div> ); } export default App;
Main.js
import store from './store' import {useState} from 'react'; const {getState,dispatch,subscribe} = store; function Main() { const [num,setNum] = useState(getState().num) const [age,setAge] = useState(getState().age) const cut = ()=>{ dispatch({type:'cutAge'}) } const add = ()=>{ dispatch({type:'addNum',payload:10}) } subscribe(()=>{ setNum(getState().num) setAge(getState().age) }) return ( <div className="App"> <h1>学习redux</h1> <hr /> <h3>数量:{num}-年龄:{age}</h3> <button onClick={cut}>点击减少年龄</button> <button onClick={add}>点击增加数量</button> </div> ); } export default Main;
单一数据源
每个应用的state被存储在一个object 中
这个object在唯一的store中
state是只读的
唯一改变state的方法是触发action
使用纯函数来执行改变
reducer描述action如何改变state
export const addNum = ()=>{ return {type:'addNum'} }
<Provider store={store}> </Provider>
import {useSelector,useDispatch} from 'react-redux'
const num = useSelector(state=>state.num)
const age = useSelector(state=>state.age)
const dispatch = useDispatch()
dispatch(addNum())
import {connect} from 'react-redux'
export default connect(state=>({name:state.name,num:state.num}),{add:addNum})(App)
组件中通过props使用: props.name,props.num,props.add
immutable: 永不可改变
常用的库: immer,immutabel,@reduxjs/toolkit
import {createStore,CombineReducers,applyMiddleware} from 'react' import {userReducer} from 'xxx' import {msgReducer} from 'yyy' import thunk from 'redux-thunk' const store = createStore(CombineReducers({ user:userReducer, msg:msgReducer }),applyMiddleware(thunk)) // thunk const setNameAsync =(data)=>{ return (dispatch,getState)=>{ setTimeout(()=>{ dispatch() },3000) } }
安装: npm i @reduxjs/toolkit react-redux -S
使用: react-redux
里面的Provider
和 useSelector
和useDispatch
使用: @reduxjs/toolkit
里面configureStore
,createSlice
可以书写可变的更新,自动转换成不可变更模式,内部集成了immer
可以书写异步的数据流,内部集成了react-thunk
export default configureStore({ reducer:{ user:UserReducer, msg:MsgReducer } })
const UserSlice = createSlice({ name:'user', initialState:{}, reducers:{ addCount(state,action) state.count = state.count+action.payload; } } }) export const {login} UserSlice.actions; export UserSlice.reducer;