• Day08React——第八天


    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 的执行。

    1. export default function App() {
    2. const [count, updateCount] = useState(0);
    3. // 空数组依赖项 componentDidMount 只在初始化渲染一次
    4. useEffect(() => {
    5. async function getList() {
    6. const res = await fetch(URL);
    7. const jsonRes = await res.json();
    8. console.log(jsonRes);
    9. }
    10. getList();
    11. }, []);
    12. //没有依赖项 componentDidMount 初始渲染和组件更新时执行
    13. useEffect(() => {
    14. console.log(99999);
    15. });
    16. // 添加特点依赖项 componentDidUpdate
    17. useEffect(() => {
    18. console.log("couont 更新了");
    19. }, [count]);
    20. return (
    21. <div>
    22. App
    23. <div>{count}div>
    24. <button
    25. onClick={() => {
    26. updateCount(count + 1);
    27. }}
    28. >
    29. +1
    30. button>
    31. div>
    32. );
    33. }

    清除副作用

    在useEffect 中编写的由渲染本身引起的对接组件外部的操作,叫做副作用模式,比如在useEffect中开启了一个定时器,我们想在组件卸载时把这个定时器卸载掉,这个过程就是清理副作用

    1. //清除副作用
    2. function Zi() {
    3. useEffect(() => {
    4. const timer = setInterval(() => {
    5. console.log("打印中......");
    6. }, 1000);
    7. return () => {
    8. clearInterval(timer);
    9. };
    10. }, []);
    11. return <div>this is Zi componentdiv>;
    12. }
    13. export default function App() {
    14. const [show, ifShow] = useState(true);
    15. return (
    16. <div>
    17. App
    18. {show && <Zi />}
    19. <button
    20. onClick={() => {
    21. ifShow(false);
    22. }}
    23. >
    24. 卸载组件
    25. button>
    26. div>
    27. );

    自定义 hook

    概念:自定义Hook 是use打头的函数,通过自定义hook函数实现逻辑的封装复用

    封装自定义hook思路:

    1. 声明一个以use打头的函数
    2. 把函数体内可复用的逻辑(只要是可复用的逻辑)
    3. 把组件中用到的状态或方法回调return出去
    4. 组件调用结构赋值
    1. function useShow() {
    2. const [show, updateShow] = useState(true);
    3. const ifShow = () => {
    4. updateShow(!show);
    5. };
    6. return {
    7. show,
    8. ifShow,
    9. };
    10. }
    11. export default function App() {
    12. const { show, ifShow } = useShow();
    13. console.log(show);
    14. return (
    15. <div>
    16. {show && <div>this is appdiv>}
    17. <button onClick={ifShow}>clickbutton>
    18. div>
    19. );
    20. }

    Redux

    Redux 是React最常用的集中状态管理工具,类似于Vue中的Pinia(Vuex),可以独立于框架运行 作用:通过集中管理的方式管理应用的状态

    基本使用

    子模块

    1. import {createSlice} from '@reduxjs/toolkit'
    2. const counterStore = createSlice({
    3. // 模块名
    4. name: "counter",
    5. // 初始数据
    6. initialState: {
    7. count: 0,
    8. },
    9. // 修改数据的同步方法
    10. reducers: {
    11. addCount(state) {
    12. state.count++;
    13. },
    14. saveCount(state) {
    15. state.count--;
    16. },
    17. },
    18. });
    19. // 结构出actionCreater
    20. const { addCount, saveCount } = counterStore.actions
    21. //获取redcer 函数
    22. const reducer = counterStore.reducer;
    23. // 导出
    24. export {addCount,saveCount}
    25. export default reducer;

    index.js 模块总入口

    1. import { configureStore } from "@reduxjs/toolkit";
    2. import counterReducer from "./modules/counterStore";
    3. export default configureStore({
    4. reducer: {
    5. // 注册子模块
    6. counter: counterReducer,
    7. },
    8. });

    index.js 将store注入react中

    1. import React from "react";
    2. import ReactDOM from "react-dom/client";
    3. import App from "./App";
    4. import { Provider } from "react-redux";
    5. import store from "./store";
    6. const root = ReactDOM.createRoot(document.getElementById("root"));
    7. root.render(
    8. // 使用中间件链接 将store注入 react中
    9. <Provider store={store}>
    10. <App />
    11. Provider>
    12. );

    app.js 页面组件使用

    1. import React from 'react'
    2. import { useSelector, useDispatch } from "react-redux";
    3. import { addCount, saveCount } from "./store/modules/counterStore.js";
    4. export default function App() {
    5. // 通过useSelector获取 store上的数据
    6. const { count } = useSelector((state) => state.counter);
    7. // 提交action传参
    8. const actions = useDispatch();
    9. return (
    10. <div>
    11. <button
    12. onClick={() => {
    13. actions(saveCount());
    14. }}
    15. >
    16. -
    17. button>
    18. <div>{count}div>
    19. <button
    20. onClick={() => {
    21. actions(addCount());
    22. }}
    23. >
    24. +
    25. button>
    26. div>
    27. );
    28. }

    redux 同步方法参数

    在reducers的同步修改方法中添加action对象参数,在调用actionCreater的时候传递参数,参数会被传递到action对象payload属性上

    1. const counterStore = createSlice({
    2. // 模块名
    3. name: "counter",
    4. // 初始数据
    5. initialState: {
    6. count: 0,
    7. },
    8. // 修改数据的同步方法
    9. reducers: {
    10. addCount(state, options) {
    11. state.count += options.payload;
    12. },
    13. saveCount(state, options) {
    14. state.count -= options.payload;
    15. },
    16. },
    17. });

    异步方法

    创建模块

    1. import { createSlice } from "@reduxjs/toolkit";
    2. import axios from "axios";
    3. const channeStore = createSlice({
    4. // 模块名
    5. name: "channe",
    6. // 初始数据
    7. initialState: {
    8. list: [],
    9. },
    10. reducers: {
    11. getList(state, options) {
    12. state.list = options.payload;
    13. },
    14. },
    15. });
    16. // 结构出actionCreater
    17. const { getList } = channeStore.actions;
    18. async function asyncGetList(actions) {
    19. const {
    20. data: {
    21. data: { channels },
    22. },
    23. } = await axios.get("http://geek.itheima.net/v1_0/channels");
    24. actions(getList(channels));
    25. }
    26. //获取redcer 函数
    27. const reducer = channeStore.reducer;
    28. // 导出
    29. export { asyncGetList };
    30. export default reducer;

    app页面上使用

    1. export default function App() {
    2. const actions = useDispatch();
    3. useEffect(() => {
    4. asyncGetList(actions);
    5. }, []);
    6. return (
    7. <div>
    8. <ul>
    9. {list.map((i) => {
    10. return <div key={i.id}>{i.name}div>;
    11. })}
    12. ul>
    13. div>
  • );
  • }
  • 相关阅读:
    前端环境搭建指南-自用
    实验1:Arduino的nRF24L01单向收发实验
    docker 命令
    5 - 1 判断题
    android 在java中执行命令的方法
    IEJoin: 提高 Databend range join 性能
    两个不起眼的站内小细节,决定你的独立站转化率
    java8 LocalDate、LocalTime、LocalDateTime
    Cyberdog GPTS建立过程笔记
    MCU通过KT6368A用SPP透传发送1K左右的数据,手机APP显示是3个包或者4个包,但是我看手册说最大一个包是512,理论应该是两个包吧,请问这正常吗?
  • 原文地址:https://blog.csdn.net/gu644335363/article/details/137853864