react-router-dom@6-----react-redux

桂智志
2023-12-01

react-router-dom v6

  • 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:'',...}

redux

  • 状态管理工具

  • 还有: vuex,mobx,...

核心概念

  • state:驱动应用的真实数据源头

  • view: 基于当前状态的ui声明式描述

  • actons: 根据用户输入在应用程序中发生的事情,触发状态的更新

单向数据流: state=>view=>actions=>state

redux的简单运用

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

react-redux

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

多个reducer和异步数据

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)
  }
}

@reduxjs/toolkit

  • 安装: npm i @reduxjs/toolkit react-redux -S

  • 使用: react-redux 里面的ProvideruseSelectoruseDispatch

  • 使用: @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;

 类似资料: