记录react的Hooks使用

379 阅读4分钟

1.ReactRouter

  1. reactRouter官网地址:reactrouter.com/en/main
  2. reactRouter安装:npm install react-router-dom
  3. reactRouter有两种模式:history模式:createBrowseRouter和hash模式:createHashRouter
  4. 配置路由表:[{path,element,children}]
  5. 声明书写法:<Route path='' element={}/>
  6. 路由生效组件:<RouterProvider router={router}/>
  7. 路由区域显示组件,相当于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);
  };
  1. useEffect的依赖项为[data]时,模拟类组件生命周期的componentDidUpdate,只要其中任何一个state改变,就会重新渲染
const [varA, setVarA] = useState(0);
  useEffect(() => {
    const timeout = setTimeout(() => setVarA(varA + 1), 1000);
    return () => clearTimeout(timeout);
  }, [varA]);

  1. 如果没有第二个数据,只有一个函数,模拟类组件的销毁时期
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}
defaultreturn 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 方法