• React 扩展、hooks的使用、路由懒加载、组件优化/传值(笔记)


    1. setState

    1.1 setState 的两种写法

    • 对象式
    • 函数式

    1.2 对象式

    // count 初始值为 0
    let { count } = this.state
    this.setState({
      count: count + 1
      // 第二个参数为一个可选的回调函数,在数据更新完成之后才会执行
    }, () => {
      console.log(count) // 1 
    })
    console.log(count) // 0
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9

    1.3 函数式

    // 对象式其实是函数式的语法糖
    this.setState((state, props) => {
      return {
        count: state.count + 1 // 返回一个新的状态
      }
    },[callback]) // 和对象式的第二个参数一样
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6

    2. lazyLoad(路由懒加载)

    import React, { Component, lazy, Suspense } from "react";
    import { Route, NavLink } from "react-router-dom";
    
    // 路由懒加载
    let About = lazy(() => import("./components/About/About"));
    let Home = lazy(() => import("./components/Home/Home"));
    
    export default class App extends Component {
      render() {
        return (
          <div className="App">
            <div>
              <NavLink to="/demo/about" children="About" />
              <NavLink to="/demo/home" children="Home" />
            </div>
            <div className="content">
              // 当组件还没有加载回来时,显示fallback中的组件/DOM元素
              <Suspense fallback={<h1>loading...</h1>}>
                <Route path="/demo/about" component={About} />
                <Route path="/demo/home" component={Home} />
              </Suspense>
            </div>
          </div>
        );
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    3. hooks

    3.1 State Hook

    // 可以使用 React.useState、也可以直接导入 useState
    import React, { useState } from "react";
    
    export default function App() {
      // [数据, 修改数据的方法]
      let [count, setCount] = React.useState(0);
      let [arr, setArr] = useState([{name: "小红", age: 18}]);
    
      function add() {
        // 传入要修改的数据
        setCount(count + 1);
      }
    
      function addInfo() {
        // 要修改的数据,会替换掉原数据
    	setArr([...arr, {name: "小黄", age: 19}])
      }
    
      return (
        <div>
          <h1>{count}</h1>
          <button onClick={add}>点我加1</button>
          <button onClick={addInfo}>点我加添加信息</button>
        </div>
      );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    3.2 Effect Hook

    import { useEffect } from "react"
    
    export default function App() {
      let [count, setCount] = React.useState(0);
    
      // 用于模拟类组件中的生命周期钩子
      useEffect(() => {
        // 组件初始化时的操作、类似于 componentDidMount
        return () => {
          // 组件销毁时的操作,类似于 componentWillUnmount
        }
        // 不写 [] 表示任何数据更新都会触发回调,写 [] 可以指定任意数量、数据更新的回调,比如:[count] count 数据更新时触发
      },[]) // 用于检测对应数据的更新,类似于 componentDidUpdate
    
      function add() {
        setCount(count + 1);
      }
    
      return (
        <div>
          <h1>{count}</h1>
          <button onClick={add}>点我加1</button>
        </div>
      );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25

    3.3 Ref Hook

    import { useRef } from "react"
    // 和 createRef 用法一样
    
    • 1
    • 2

    4. Fragment(虚拟DOM)

    // Fragment 和 vue 中的 template 很相似
    import { Fragment } from "react"
    
    ...render(){
      // 在页面中不会生成dom,也可以使用 <> 效果一样,但它并不支持 key 或属性
      return <Fragment></Fragment>
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7

    5. Context(祖孙传值)

    // 用于祖孙组件之间的传值
    import { createContext, useContext } from "react";
    
    // 创建 context
    const MyContext = createContext();
    // Provider:传入的数据,Consumer:接收的数据
    const { Provider, Consumer } = MyContext;
    
    function App() {
      return (
    	<div>
    	  // 只可以写 value
    	  <Provider value="要传入的数据">
    	    // 后代组件	
    	  </Provider>
    	</div>
      )
    }
    
    // 后代组件1
    function Demo1(){
      return (
        <div>
          <Consumer>
            {(value) => {
              // value:接收到的数据
            }}
          </Consumer>
        </div>
      )
    }
    
    // 后代组件2
    function Demo2() {
      // 接收到的数据
      const value = useContext(MyContext)
      return <div></div>
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26
    • 27
    • 28
    • 29
    • 30
    • 31
    • 32
    • 33
    • 34
    • 35
    • 36
    • 37
    • 38

    6. 组件优化

    6.1 Component 的2个问题

    1. 只要执行了 setState(),即使不改变状态数据,组件也会重新 render
    2. 只要当前组件重新 render,子组件也会重新 render

    6.2 解决方案

    只有当前组件的 state 或 props 修改时,才会 render

    1. 设置 shouldComponentUpdate 声明周期方法
      shouldComponentUpdate(nextState, nextProps) {
        // 对比 this.state、nextState 和 this.props、nextProps
        // 如果改变了就返回 true,如果没有改变就返回 false
      } 
      
      • 1
      • 2
      • 3
      • 4
    2. 使用 PureComponent
      import { PureComponent } from "react"
      class App extends PureComponent {
        // 这种已经进行了处理,可以直接使用
        // 但是使用时需要注意两点问题
        //  1. 使用 setState 修改时不要使用同一个地址,地址没变判定为未修改
        //  2. 不要直接在组件标签上,通过回调的形式写 render props,会抵消掉 PureComponent 的作用
      }
      
      • 1
      • 2
      • 3
      • 4
      • 5
      • 6
      • 7

    7. Render Props(逆向传值)

    // 这种方式可以向上传递数据,类似于 vue 中的作用域插槽
    function App() {
      return (
            <div>
                <p> 我是App组件</p>
                <Child render={(value) => <span>{`name:${value.name},age:${value.age}`}</span>} />
            </div>
        );
    }
    
    function Child(props) {
      return (
            <div>
                <p> 我是Child组件</p>
                {props.render({ name: "小红", age: 18 })}
            </div>
        );
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18

    8. 错误边界

    // 用于捕获子组件生命周期的错误,只在生产环境会有效果
    
    class App extends Component {
      // 子组件生命周期出错就会触发
      static getDerivedStateFromError() {
    	return {
    	  hasError: true
        }
      }
    
      componentDidCatch() {
        console.log("打印错误信息")
      }
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14

    9. 组件通信

    • 父子:props、renderProps(逆向传递)
    • 兄弟:redux(集中式管理)、发布订阅
    • 祖孙:redux(集中式管理)、context、发布订阅
  • 相关阅读:
    前端实现给文字添加动态背景
    Nginx:移植Nginx内存池 | 附测试用例
    拓展卡尔曼滤波(Kalman)附Matlab代码
    2024懒人精灵七天从入门到精通实战课程(付源码)
    LintCode 87: Remove Node in Binary Search Tree BST操作经典题
    代码整洁之道-读书笔记之对象和数据结构
    可替代角雷达,这款纯固态补盲激光雷达什么来头?
    视频推流测试——使用ffmpeg进行推流生成rtsp视频流
    Promise的使用与async/await的使用
    PHP和JAVA AES加解密问题
  • 原文地址:https://blog.csdn.net/weixin_60547084/article/details/126041809