react 常用 hook Hoc高阶组件

295 阅读4分钟

useState

 * React主要是通过setState, useState方法来更新状态, 状态更新之后, 组件也会重新渲染
1. useState 有2种初始化的方式 
第一种 useState(值) 
第二种 useState(() => { 
  写逻辑 
  return 值 
})

2. useState 全都是异步的
修改完以后 如果想立刻获取上一次的值 可以使用 useState的 set方法 接收一个回调函数
setX(pre => {
  // pre 就是上一的值
  return pre
})

3. useState 为什么要做成异步的? 
如果是同步, 比如我连续调用5次, 页面就会刷新5次, 浪费性能, 所以把它做成异步的, 对同一个值进行多次 setState
setState的批量更新策略会对其进行覆盖 取最后一次的执行结果, 如果是同时 setState 多个不同的值, 在更新时会对其进行合并批量更新

// useState 使用方法
  export default () => {
    // 异步
    const [x1, setX1] = useState(1)
    const [x2, setX2] = useState(() => {
      // ajax
      if (true) {
        return 3

      } else {
        return 2
      }
    })

    const onClick = opt => {
      // 异步 (等一小会)
      setX1(x1 + 1)
      // prevState 上一次的值
      setX1(prevState => {
        console.log(prevState, 'prevState');
        // return 出去的值就是 x1 的值
        return prevState
      })
      console.log(x1, 'x1');
    }

    return (
      <div>
        <h1>{x1}</h1>
        <Button onClick={onClick}>改变x1</Button>
      </div>
    )
  };

useEffect

  • useEffect 可以模拟哪些生命周期
    1. componentDidMount // 加载完成的
    2. componentDidUpdate // 更新阶段
    3. componentWillUnmount // 卸载阶段
// * 加载阶段
useEffect(() => {
  // setInterval, setTimeout 会形成闭包, 会保存 time 的复制值, 该值与外面的 time
  // 不是同一个值
  setInterval(() => {
    setTime(time - 1)
    // 始终输出 3
    console.log(time, 'xxx');
  }, 1000)
}, [])

// * 更新阶段
useEffect(() => {
  // setInterval, setTimeout 会形成闭包, 会保存 time 的复制值, 该值与外面的 time
  // 不是同一个值
  setInterval(() => {
    setTime(time - 1)
    // 始终输出 3
    console.log(time, 'xxx');
  }, 1000)
}, [data])


// * 卸载阶段
useEffect(() => {
  return ()=>{
      
  }
}, [data])

useRef 与 createRef的区别

  • useRef
    在页面渲染时只执行一次, 有初始值, 可以用于保存上一次的值, 可以获取dom节点, useRef在每次渲染时返回同一个ref对象, 只有current读写
  • createRef
    每次组件渲染都会执行, 没有初始值, 主要用于class组建中创建refs
  // 1. createRef 只要组件重新渲染 createRef 就会重新重新执行
  export default () => {
    const [x1, setX1] = useState(() => {
      return 1
    })
    // 特性: useRef 页面渲染的时候只执行一次
    // 特性: 只有 current 读写
    // 返回值: { current: undefined } 内存地址 abc
    // 作用1. 获取DOM
    // 作用2. 存储上一次的值
    const ref = useRef()
    const ref2 = createRef()

    const onClick = opt => {
      // ref.current === 1
      ref.current = x1
      ref2.current = x1
      // 异步
      setX1(x1 + 1)
    }

    return (
      <div>
        <h1>{x1}</h1>
        <h1 ref={ref}>小花</h1>
        <h1 ref={ref2}>小蓝</h1>
        <Button onClick={onClick}>改变x1</Button>
      </div>
    )
  }

useMemo

  • useMemo 有两个参数,一个回调函数,一个依赖,回调函数里必须有返回值
  • useMemo 的特性是缓存return出来的值,如果依赖为空 useMemo缓存的值永远不会改变,如果依赖改变,缓存的值会重新发生改变
  • useMemo 主要用来缓存计算结果的值
 /* 
    特性: 
    1. 有一个返回值 回调函数里 retrun 的值
    2. useMemo 立刻执行的

    const fn = useMemo(() => {
      return 123
      return () => {
        
      }
    }, [])

  */
  export default connect(({ loading }) => {
    return {
      loading: !!loading.effects['upload/fetch'],
    }
  })(UseCallback)
  function UseCallback (props) {
    const { dispatch, loading } = props
    const [form] = Form.useForm()
    const [fileList, setFileList] = useState([])
    const [x, setX] = useState(20000)
    const [y, setY] = useState(20000)

    // 第一次刷新 x === 20000
    // 第二次 x === 20001
    const x1 = useMemo(() => {
      console.log('我执行了');
      let sum = 0
      for (let i = 0; i < x; i++) {
        sum += i
      }
      return sum
    }, [x])

    return (
      <div style={{background: '#000'}}>
        <h1>x: {x1}</h1>
        <h1>y: {y}</h1>
        <h1 onClick={() => setX(x + 1)}>x: {x}</h1>
        <h1 onClick={() => setY(y + 1)}>y: {y}</h1>
      </div>
    )
  }
  

useCallback

  • useCallback 有两个参数, 第一个参数是一个回调函数, 第二个参数是一个依赖
  • useCallback 缓存一个函数, 依赖为空的时候,缓存的函数不会改变,依赖改变,缓存的函数就跟着改变
  • useCallback 是 useMemo 语法糖,一个缓存函数,一个缓存值
  • useCallback 返回函数而不调用 useMemo 调用函数并且返回结果
  /* 
    用途: 父组件刷新 子组件不刷新

    返回一个新函数 如果依赖是空 新函数的指针永远不变
    依赖是空 useCallback 永远只执行一次
    const fn = useCallback(() => {
      
    }, [])

    // 如果依赖改变了 重新返回指针变了的新函数
    const fn = useCallback(() => {

    }, [x])
    
  */
  export default function UseCallback () {
    const [x, setX] = useState(0)

    // console.log('我是父组件,我执行了');

    // fn 保存的 123指针 -> () => console.log(1)
    // 第一次渲染 fn 123
    // 第二次 直接把 123 指针 给 fn
    // 第三次 直接把 123 指针 给 fn
    const fn = useCallback(() => {
      // console.log(1)
    }, [])

    return (
      <>
        <h1 onClick={() => setX(x + 1)}>x: {x}</h1>
        <QuseCallBack 
          fn={fn} // 123
        />
      </>
    )
  }

useContext

useContext 自定义默认值
image.png
useContext 父子组件传值 SE9@1ER_2X15@8WQAOP6GQW.png

useContext 方法接收一个 context 对象(React.createContext 的返回值)并返回该 context 的当前值。当前的 context 值由上层组件中距离当前组件最近的 <MyContext.Provider>value prop 决定。

当组件上层最近的 <MyContext.Provider> 更新时,该 Hook 会触发重渲染,并使用最新传递给 MyContext provider 的 context value 值。即使祖先使用 React.memoshouldComponentUpdate,也会在组件本身使用 useContext 时重新渲染。

可以理解为,useContext(MyContext) 相当于 class 组件中的 static contextType = MyContext 或者 <MyContext.Consumer>

useContext(MyContext) 只是让你能够读取 context 的值以及订阅 context 的变化。你仍然需要在上层组件树中使用 <MyContext.Provider> 来为下层组件提供 context。

Hoc高阶组件

image.png

function Hoc(WrappedComponent) {
  return () => {
    const [xy, setXY] = useState({
      x: 0,
      y: 0,
    });
    useEffect(() => {
      const fun = ({ clientX, clientY }) => {
        setXY({
          x: clientX,
          y: clientY,
        });
      };
      // DOM2
      document.addEventListener('mousemove', fun);
      return () => {
        document.removeEventListener('mousemove', fun);
      };
    }, []);

    return <WrappedComponent xy={xy} />;
  };
}

function Home(props) {
  const { xy } = props;
  return (
    <div>
      <h1>
        {xy.x}--{xy.y}
      </h1>
    </div>
  );
}
export default Hoc(Home);

还没写完!! 自己总结的 有问题的及时联系我删改哦~ 谢谢! 捣蛋兔1.png

捣蛋兔2.png

捣蛋兔4.png

捣蛋兔3.png