React Hooks 之 useReducer useRef useContext和useMemo 的用法

之前文章中我们有讲到的 useState hook 和 useEffect hook 的一些概念和基本用法,趁着周末空闲时间,我们一起来看看 React 为我们提供的其他 hooks 的一些基本使用吧。

useReducer

useReducer hook 接收两个参数,第一个是参数是一个函数(这是一个 reducer函数:它接收两个参数 state 和 action,它会根据 action 类型返回一个新的state),第二个参数是一个初始状态(intialState)。语法如下:

const [newState, dispatch] = useReducer((state, action) => {
  //根据派发出去的 action 类型,返回一个 newState
}, intialState)

看一个例子:

const Counter = () => {
  //count对应 reducer 返回的nweState
  //dipatch 负责派发一个 action(动作)
  //action是一个具有 type 属性的一个javascript对象
  const [count, dispatch] = useReducer((state, action) => {
    switch (action.type) {
      case 'add':
        return state + 1;
      case 'sub':
        return state - 1;
      default:
        return state;
    }
  }, 0)
  return (
    <div>
      <div>CountSum: {count}</div>
      <button onClick={() => dispatch({ type: 'add' })}>Add</button>
      <button onClick={() => dispatch({ type: 'sub' })}>Substract</button>
    </div>
  )
}

export default Counter;

useReducer hook 的流程可以总结为:

事件发生 -->调度方法(dispatch)派发一个动作(action) --> reducer 根据派发的动作类型(action.type)返回一个新的状态(newState)

useRef hook

Refs 用于访问在 render 呈现的 DOM 或 React 元素。在以前的 React 版本中使用refs的标准方法是这样的:

//16.3提供
class RefHook extends React.Component {
  constructor(props) {
    super(props);
    //创建ref
    this.myRef = React.createRef();
  }

  render() {
    return <div ref={this.myRef}></div>
  }
}
export default RefHook;

现在可以使用 useRef hook:

//16.8提供
function RefHook() {

  const myRef = useRef();
  function handleChange() {
    console.log(myRef);
  }

  return <div onChange={handleChange} ref={myRef}></div>
}

export default RefHook;

useContext hook

Context API 解决了 React 最大的问题之一就是 props 多层组件传递。在以前的版本中:

const ThemeContext = React.createContext();
function ContextComponent() {
  return (
    <ThemeContext.Provider value="dark">
      <ThemeButton />
    </ThemeContext.Provider>
  )
}

function ThemeButton() {
  return (
    <ThemeContext.Consumer>
      {(theme) => <div> This is theme: {theme} </div>}
    </ThemeContext.Consumer>
  )
}

export default ContextComponent;

useContext hook 提供了使用上下文的很多优化的方式。

import React, { useContext } from 'react';

const ThemeContext = React.createContext();
function ContextComponent() {
  return (
    <ThemeContext.Provider value="dark">
      <Theme />
    </ThemeContext.Provider>
  )
}

function Theme() {
  const theme = useContext(ThemeContext);
  return (
    <div> This is theme: {theme} </div>
  )
}

export default ContextComponent;

useMemo hook

React有一个名为 useMemo 的钩子,它让我们记忆复杂而昂贵的函数,这样我们就可以避免每次重复的渲染。

它是采用了 Memoization 思想 它是 JavaScript 中的一种技术,通过缓存结果并在下一个操作中重新使用缓存来加速查找费时的操作。

比方说,我们必须编写一个函数来查找给定数字的平方。

const calc = num => {
  return num * num;
}
calc(4); // 16
calc(5); // 25
calc(35); // 1225
calc(35); // 1225
calc(5); // 25
calc(35); // 36

我们计算了两次 35 的平方,这还好因为它不是什么密集的操作,如果是非常耗时的操作,就会变得很昂。采用 Memoization 可以这么做:

const cache = {};
const calc = num => {
  let result = cache[num];
  if(!result) {
    result = num * num;
    cache[num] = result;
  }
  return result;
}
calc(4);
calc(5);
calc(35); //1225
calc(35); //1225
console.log(cache); // {4: 16, 5: 25, 35: 1225}

从上边的例子中我们可以看到,当我们再计算 35 的平方时,不需要重新计算,而直接从缓存中选择值即可,提高了程序的性能。

在 React 中,有些时候我们不想每次都重新渲染组件,基于 Memoization 思想 useMemo hook 就是负责记忆相应的组件,只有在数据发生变化时组件才会重新渲染。

function Parent({ a, b }) {
  // 当 a b 有一个发生变化时 才重新渲染
  const child1 = useMemo(() => <Child1 a={a} b={b}/>, [a, b]);
  // 当 b 发生变化时 才重新渲染
  const child2 = useMemo(() => <Child2 b={b} />, [a, b]);
  return (
    <>
      { child1 }
      { child2 }
    </>
  )
}

原文发布于微信公众号 - 前端infoQ(webinfoq)

原文发表时间:2019-03-04

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

发表于

我来说两句

0 条评论
登录 后参与评论

扫码关注云+社区

领取腾讯云代金券