useEffect
概念:useEffect 是一个 React Hook 函数,用于在React组件中创建不是由事件引起而是由渲染本身引起的操作,比如发送AJAx请求,更改daom等等
需求:在组件渲染完毕后,立刻从服务器获取频道列表数据并显示到页面
语法:useEffect( ()=>{},[] )
参数1是一个函数,可以把它叫做副作用函数,在函数内部可以放置要执行的操作
操作2是一个数组(可选参),在数组里放置依赖项,不同依赖项会影响第一个参数函数的执行,当是一个空数组的时候,副作用函数只会在组件渲染完毕之后执行一次
React 18 中的 useEffect hook 没有依赖项时,表示该 effect 不依赖于任何状态或 props 的变化,只在组件挂载和卸载时执行一次。这与 React 17 中的类式组件中 componentDidMount 和 componentWillUnmount 生命周期方法的功能类似。
当 useEffect hook 中传入一个空数组作为依赖项时,表示该 effect 只在组件挂载时执行一次,类似于 React 17 中的 componentDidMount 生命周期方法。
而当 useEffect hook 中传入特定的依赖项时,表示该 effect 会在这些依赖项发生变化时执行。这与 React 17 中类式组件中 componentDidUpdate 生命周期方法的功能类似,可以根据特定的依赖项来触发 effect 的执行。
export default function App() {const [count, updateCount] = useState(0);// 空数组依赖项 componentDidMount 只在初始化渲染一次useEffect(() => {async function getList() {const res = await fetch(URL);const jsonRes = await res.json();console.log(jsonRes);}getList();}, []);//没有依赖项 componentDidMount 初始渲染和组件更新时执行useEffect(() => {console.log(99999);});// 添加特点依赖项 componentDidUpdateuseEffect(() => {console.log("couont 更新了");}, [count]);return (<div>App<div>{count}</div><buttononClick={() => {updateCount(count + 1);}}>+1</button></div>);
}
清除副作用
在useEffect 中编写的由渲染本身引起的对接组件外部的操作,叫做副作用模式,比如在useEffect中开启了一个定时器,我们想在组件卸载时把这个定时器卸载掉,这个过程就是清理副作用
//清除副作用
function Zi() {useEffect(() => {const timer = setInterval(() => {console.log("打印中......");}, 1000);return () => {clearInterval(timer);};}, []);return <div>this is Zi component</div>;
}export default function App() {const [show, ifShow] = useState(true);return (<div>App{show && <Zi />}<buttononClick={() => {ifShow(false);}}>卸载组件</button></div>);
自定义 hook
概念:自定义Hook 是use打头的函数,通过自定义hook函数实现逻辑的封装复用
封装自定义hook思路:
- 声明一个以use打头的函数
- 把函数体内可复用的逻辑(只要是可复用的逻辑)
- 把组件中用到的状态或方法回调return出去
- 组件调用结构赋值
function useShow() {const [show, updateShow] = useState(true);const ifShow = () => {updateShow(!show);};return {show,ifShow,};
}export default function App() {const { show, ifShow } = useShow();console.log(show);return (<div>{show && <div>this is app</div>}<button onClick={ifShow}>click</button></div>);
}
Redux
Redux 是React最常用的集中状态管理工具,类似于Vue中的Pinia(Vuex),可以独立于框架运行 作用:通过集中管理的方式管理应用的状态
基本使用
子模块
import {createSlice} from '@reduxjs/toolkit'const counterStore = createSlice({
// 模块名name: "counter",
// 初始数据initialState: {count: 0,},
// 修改数据的同步方法reducers: {addCount(state) {state.count++;},saveCount(state) {state.count--;},},
});// 结构出actionCreater
const { addCount, saveCount } = counterStore.actions//获取redcer 函数
const reducer = counterStore.reducer;
// 导出
export {addCount,saveCount}
export default reducer;
index.js 模块总入口
import { configureStore } from "@reduxjs/toolkit";import counterReducer from "./modules/counterStore";export default configureStore({reducer: {// 注册子模块counter: counterReducer,},
});
index.js 将store注入react中
import React from "react";
import ReactDOM from "react-dom/client";
import App from "./App";
import { Provider } from "react-redux";
import store from "./store";const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(// 使用中间件链接 将store注入 react中<Provider store={store}><App /></Provider>
);
app.js 页面组件使用
import React from 'react'
import { useSelector, useDispatch } from "react-redux";
import { addCount, saveCount } from "./store/modules/counterStore.js";export default function App() {// 通过useSelector获取 store上的数据const { count } = useSelector((state) => state.counter);// 提交action传参const actions = useDispatch();return (<div><buttononClick={() => {actions(saveCount());}}>-</button><div>{count}</div><buttononClick={() => {actions(addCount());}}>+</button></div>);
}
redux 同步方法参数
在reducers的同步修改方法中添加action对象参数,在调用actionCreater的时候传递参数,参数会被传递到action对象payload属性上
const counterStore = createSlice({// 模块名name: "counter",// 初始数据initialState: {count: 0,},// 修改数据的同步方法reducers: {addCount(state, options) {state.count += options.payload;},saveCount(state, options) {state.count -= options.payload;},},
});
异步方法
创建模块
import { createSlice } from "@reduxjs/toolkit";
import axios from "axios";const channeStore = createSlice({// 模块名name: "channe",// 初始数据initialState: {list: [],},reducers: {getList(state, options) {state.list = options.payload;},},
});// 结构出actionCreater
const { getList } = channeStore.actions;async function asyncGetList(actions) {const {data: {data: { channels },},} = await axios.get("http://geek.itheima.net/v1_0/channels");actions(getList(channels));
}//获取redcer 函数
const reducer = channeStore.reducer;
// 导出
export { asyncGetList };export default reducer;
app页面上使用
export default function App() {const actions = useDispatch();useEffect(() => {asyncGetList(actions);}, []);return (<div><ul>{list.map((i) => {return <div key={i.id}>{i.name}</div>;})}</ul></div></div>);
}