React

关注公众号 jb51net

关闭
首页 > 网络编程 > JavaScript > javascript类库 > React > React渲染优化useImmer

一文详解React渲染优化之useImmer

作者:Ryun

在React日常开发中,我们常常被重复渲染或无意义渲染所折磨,穷尽脑汁,做各种优化:memo、useMemo、useCallback、immutable等,本文主要讲述immutable的简约版Immer,感兴趣的同学可以一起来学习

从一个例子开始

import { FC, useState, useEffect } from 'react';

const App: FC = () => {
  const [list, setList] = useState({ a: 1 });

  useEffect(() => {
    setList({ a: 1 });
  }, []);

  console.log('测试');

  return (
    <>
      <h1>Hello Web3 React {list.a}</h1>
    </>
  );
};

export default App;

渲染检查工具

why-did-you-render, 可以在开发时,帮你检测无意义的渲染

/// <reference types="@welldone-software/why-did-you-render" />
import React from 'react';

if (process.env.NODE_ENV === 'development') {
  // eslint-disable-next-line
  const whyDidYouRender = require('@welldone-software/why-did-you-render');
  whyDidYouRender(React, {
    onlyLogs: true,
    titleColor: 'green',
    diffNameColor: 'darkturquoise',
    trackHooks: true,
    trackAllPureComponents: true,
  });
}

要解决这个问题,需要我们使用到Immer

Immer 与 UseImmer

Immer是如何工作的?

Immer优点

使用

state + Immer

useImmer

import { FC, useEffect } from 'react';
import { useImmer } from '@hooks/useImmer';

const App: FC = () => {
  const [list, setList] = useImmer({ a: 1 });

  useEffect(() => {
    // setList({ a: 1 });
    setList(draft => {
      draft.a = 1;
    });
  }, []);

  console.log('测试');

  return (
    <>
      <h1>Hello Web3 React {list.a}</h1>
    </>
  );
};

export default App;

观察控制台,发现已经没有无意义渲染的提示了,It's wonderful!

useEffect(() => { 
  // setList({ a: 1 });
  setList(draft => {
    draft.a = 1;
  }); 
},[]);

自己动手实现hooks-useImmer

import { useCallback, useState } from 'react';
import { produce, Draft, freeze } from 'immer';

/**
 * 定义函数的签名
 * initialState 可以是一个数据,也可以是一个函数
 * useImmer 返回元组,类似 [state, setState] = useImmer(data);
 * Draft 中间状态
 * (() => S) 自执行函数
 */
export type DraftFunction<S> = (draft: Draft<S>) => void;
export type Updater<S> = (arg: S | DraftFunction<S>) => void;
export type ImmerHook<S> = [S, Updater<S>];
export function useImmer<S = any>(initialState: S | (() => S)): ImmerHook<S>;

/**
 * 实现
 * @param initialState
 */
export function useImmer<T>(initialState: T) {
  // const [state, setState] = useState(initialState);
  // 冻结 state,第二参数 true,表示深度冻结,对象不能修改了
  const [value, updateValue] = useState(() =>
    freeze(typeof initialState === 'function' ? initialState() : initialState, true)
  );

  // 使用 useCallback,放置组件间传递,产生句柄
  return [
    value,
    useCallback((updater: Updater<T>) => {
      if (typeof updater === 'function') {
        updateValue(produce(updater));
      } else {
        updateValue(freeze(updater));
      }
    }, []),
  ];
}

以上就是一文详解React渲染优化之useImmer的详细内容,更多关于React渲染优化useImmer的资料请关注脚本之家其它相关文章!

您可能感兴趣的文章:
阅读全文