React新版本特性解读

  • render支持返回数组和字符串
  • 错误边界
  • 提升SSR渲染速度,支持流式渲染
  • 减少文件体积
  • 生命周期函数更新

    • 由于异步渲染的改动,有可能会导致componentWillMount,componentWillReceiveProps,componentWillUpdate,所以抛弃三个生命周期函数
    • createContext:不必一层层传递,可使用此方法指定生效范围
    • createRef:同上
    • hooks:开发方式大更新

      hooks出现的意义

  • hooks之间的状态是独立的,有自己独立的上下文,不会出现混淆状态的情况

  • 让函数组件有了状态管理
  • 解决了组件树不直观、类组件难维护、逻辑不易复用的问题
  • 由于函数每次渲染都会执行,所以React中多了一个状态控制,传入第二个参数,这样就可以避免函数重复执行的副作用

    应用场景

  • 利用hooks取代生命周期函数

  • 让函数组件加上状态
  • 处理发送请求
  • 存取数据
  • 做好性能优化

    定时器⏲清理

    简单分析:

  • 首先useEffect方法,是react新增的,它是componentDidMountcomponentDidUpdatecomponentWillUnmount三个生命周期的合集,

  • 也就是之前的写法,上面三生命周期里会执行到的操作,useEffect都会去做;
  • useEffect方法里return 一个方法,它是可以在组件卸载时执行的,
  • 清除定时器它有自己的方式,const intervalRef = useRef();指定赋值后能同步更新,之前的timer手动执行没有拿到timer所以没有清除掉;

参考链接:https://blog.csdn.net/weixin_43254766/article/details/84842106
image.png

hooks API

useState

  • 作用
    • 函数组件添加状态
  • 注意事项
    • 初始化以及更新state
    • 用来声明状态变量 ```javascript import React, { useState } from “react”;

function StateFunction() { // 使用useState来创建状态 // 1.引入 // 2.接收一个参数作为初始值 // 3.返回一个数组,第一个值为状态,第二个值为改变状态的函数 const [name, setName] = useState(“函数”); return (

setName(“被set过一次的函数”)}> 这是一个函数组件 - {name}
); }

export default StateFunction;

  1. <a name="Q8rCi"></a>
  2. #### useEffect 副作用hooks
  3. - 作用
  4. - 给没有生命周期的组件,添加结束渲染的信号
  5. - 注意事项
  6. - 在render之后执行
  7. <a name="78xOD"></a>
  8. #### useLayoutEffect-监测DOM
  9. - 作用
  10. - DOM更新完成后执行某个操作
  11. - 相当于类组件里的componentWillmount
  12. - 注意事项
  13. - 有DOM操作的副作用hooks
  14. - 在DOM更新之后执行
  15. ```javascript
  16. import React, { useState, useEffect, useLayoutEffect } from "react";
  17. function StateFunction() {
  18. // 相似的用法
  19. // 接收一个函数作为参数
  20. // 接收第二个参数:依赖列表,只有依赖更新时,才会执行函数
  21. // 返回一个函数,先执行返回函数,再执行参数函数
  22. // 不同点
  23. // useEffect 执行时机在render之后
  24. // useLayoutEffect 执行时机在dom更新之后
  25. const [Num, setNum] = useState(1);
  26. useEffect(() => {
  27. console.log("useEffect");
  28. document.body.addEventListener("a", () => {});
  29. return () => {
  30. document.body.removeEventListener("a", () => {});
  31. };
  32. }, [Num]);
  33. useLayoutEffect(() => {
  34. console.log("useLayoutEffect");
  35. document.body.addEventListener("a", () => {});
  36. return () => {
  37. document.body.removeEventListener("a", () => {});
  38. };
  39. });
  40. return (
  41. <div onClick={() => setNum((Num) => Num + 1)}>这是一个函数组件 - {Num}</div>
  42. );
  43. }
  44. export default StateFunction;

image.png
useLayoutEffect会先打印,useEffect后打印。**useLayoutEffect模拟的是componentWillmount,useEffect模拟的时候**componentDidmount。

useMemo

  • 作用
    • 让组件中的函数跟随状态更新
  • 注意事项
    • 优化函数组件中的功能函数 ```javascript import React, { useState, useEffect, useLayoutEffect, useMemo } from “react”;

function StateFunction() { const [Num, setNum] = useState(1); const [age, setAge] = useState(18);

// const getDoubleNum = () => { // console.log(“获取双倍的num”); // return 2 * Num; // };

// useMemo使用方法 // 1.接收一个函数作为参数 // 2.第二个参数为依赖列表,useEffect,useLayoutEffect进行对比 // 3.返回的是一个值,不是函数 const getDoubleNum = useMemo(() => { console.log(“获取双倍的num”); return 2 * Num; }, [Num]);

return (

setAge((age) => age + 1)}> Num的值为 - {getDoubleNum} age的值为 - {age}
); }

export default StateFunction;

  1. <a name="t4hwX"></a>
  2. #### useCallback
  3. - 作用
  4. - 跟随状态更新执行
  5. - 注意事项
  6. - 只有依赖项改变的时候才会执行
  7. - `useMemo(()=>fn, deps)` 相当于 `useCallback(fn, deps)`
  8. ```javascript
  9. import React, { useState, useCallback, Children, useEffect } from "react";
  10. function StateFunction() {
  11. const [Num, setNum] = useState(1);
  12. const [age, setAge] = useState(18);
  13. // const getDoubleNum = () => {
  14. // console.log("获取双倍的num");
  15. // return 2 * Num;
  16. // };
  17. // 在使用方法上,useCallback与useMemo相同
  18. // 不同点
  19. // useMemo返回的是一个值,useCallback返回的是一个函数
  20. // useMemo缓存的是一个值,useCallback缓存的是一个函数
  21. const getDoubleNum = useCallback(() => {
  22. console.log("获取双倍的num");
  23. return 2 * Num;
  24. }, [Num]); // 依赖是[], 缓存的 函数不变,子组件不会更新。 依赖的是[Num],缓存的函数每次都会更新,子组件也会更新
  25. return (
  26. <div onClick={() => setAge((age) => age + 1)}>
  27. Num的值为 - {getDoubleNum()}
  28. age的值为 - {age}
  29. <Child callback={getDoubleNum}></Child>
  30. </div>
  31. );
  32. }
  33. // 子组件
  34. function Child(props) {
  35. useEffect(() => {
  36. console.log("callback更新了");
  37. }, [props.callback]);
  38. return <div>child</div>;
  39. }
  40. export default StateFunction;

useRef 长久保存数据

  • 作用
    • 长久保存数据
  • 注意事项
    • 返回一个子元素的索引,此索引在整个生命周期中保持不变
    • 对象发生改变,不通知。属性变更不会触发重新渲染(重新赋值ref.current 不会触发重新渲染) ```javascript import React, { useState, useRef, useEffect } from “react”;

function StateFunction() { const [Num, setNum] = useState(1);

const ref = useRef(); useEffect(() => { ref.current = setInterval(() => { setNum((Num) => Num + 1); }, 400); }, []);

useEffect(() => { if (Num > 10) { console.log(“超过10了”, ref.current); clearInterval(ref.current); } }, [Num]);

return

Num的值为 - {Num}
; }

export default StateFunction;

  1. <a name="IlBhg"></a>
  2. #### useContext 组件之间共享状态
  3. - 作用
  4. - 带着子组件去流浪
  5. - 注意事项
  6. - 上层数据发生改变,肯定会触发重现渲染
  7. ```javascript
  8. import React, { useState, useContext, createContext } from "react";
  9. // 1. 引入useContext, createContext
  10. // 2. 通过createContext创建一个context句柄
  11. // 3. Context.Provider来确定数据共享范围
  12. // 4. 通过value来分发内容
  13. // 5. 在子组件中,通过useContext(context句柄)来获取数据
  14. const Context = createContext(null);
  15. function StateFunction() {
  16. const [Num, setNum] = useState(1);
  17. return (
  18. <div onClick={() => setNum((Num) => Num + 1)}>
  19. Num的值为 - {Num}
  20. <Context.Provider value={Num}>
  21. <Item1 />
  22. <Item2 />
  23. </Context.Provider>
  24. </div>
  25. );
  26. }
  27. function Item1() {
  28. const num = useContext(Context);
  29. return <div>子组件{num}</div>;
  30. }
  31. function Item2() {
  32. const num = useContext(Context);
  33. return <div>子组件{num}</div>;
  34. }
  35. export default StateFunction;

image.png

useReducer 复杂逻辑简单化

  • 作用
    • 去其他地方借资源
  • 注意事项
    • 函数组件的redux操作 ```javascript import React, { useState, useReducer } from “react”;

// redux必须的内容 // store reducer

// useReducer使用方法 // 1. 需要创建数据仓库store和仓库管理者reducer // 2. 通过useReducer(reducer, store)来获取state和dispatch const store = { num: 10, };

const reducer = (state, action) => { switch (action.type) { case “changeNum”: return { …state, num: action.num, }; default: return { …state, }; } }; function StateFunction() { const [state, dispatch] = useReducer(reducer, store);

return (

{ dispatch({ type: “changeNum”, num: 100, }); }} > Num的值为 - {state.num}
); }

export default StateFunction;

  1. <a name="HnuGC"></a>
  2. #### 自定义Hooks
  3. - 作用
  4. - 自定义Hooks以支持特殊场景
  5. - 自定义Hooks注意事项
  6. - 引入react和自己需要的hook
  7. - 创建自己的hook函数
  8. - 返回一个数组,**数组中第一个内容是数据,第一个是修改数据的函数**
  9. - 将自己定义的hook函数暴露出去
  10. - 在自己的业务组件中引入并使用
  11. - **实现模拟的数据接口请求功能**
  12. - useLoadDate.js
  13. ```javascript
  14. import React, { useState, useEffect } from "react";
  15. // 如何实现模拟的数据接口请求功能
  16. function useLoadData() {
  17. const [num, setNum] = useState(1);
  18. useEffect(() => {
  19. setTimeout(() => {
  20. setNum(2);
  21. }, 1000);
  22. }, []);
  23. return [num, setNum];
  24. }
  25. export default useLoadData;
  1. import React from "react";
  2. import useLoadData from "../utils/useLoadDate";
  3. function StateFunction() {
  4. const [num, steNum] = useLoadData();
  5. return <div onClick={() => {}}>Num的值为 - {num}</div>;
  6. }
  7. export default StateFunction;
  • 实现本地自定义的reducer
    • useLocalReducer.js ```javascript import React, { useReducer } from “react”;

// 数据仓库 const store = { age: “111”, };

// 管理者 const reducer = (state, action) => { switch (action.type) { case “age”: return { …state, age: action.age, }; default: return { …state, }; } };

function useLocalReducer() { const [state, dispatch] = useReducer(reducer, store);

return [state, dispatch]; }

export default useLocalReducer;

  1. ```javascript
  2. import React from "react";
  3. import useLoadData from "../utils/useLoadDate";
  4. import useLocalReducer from "../utils/useLocalReducer";
  5. function StateFunction() {
  6. const [state, dispatch] = useLocalReducer();
  7. const [num, steNum] = useLoadData();
  8. return (
  9. <div
  10. onClick={() => {
  11. dispatch({
  12. type: "age",
  13. age: "222",
  14. });
  15. }}
  16. >
  17. Num的值为 - {num} --{state.age}
  18. </div>
  19. );
  20. }
  21. export default StateFunction;

使用hooks实现购物车功能

  • 购物车功能
    • 添加商品
    • 显示商品
    • 删除
    • 全选

image.png
image.png

  • 自定义hooks-useLocalContext ```javascript import React from ‘react’

// 引用单例模式,将context做唯一处理 const LocalContext = () => { // 闭包的方式 let context return () => { if(!context){ context = React.createContext(null) } return context } } export default LocalContext() // 先执行一次 ```