[React] Preventing extra re-rendering with function component by using React.memo and useCallback

Got the idea form this lesson. Not sure whether it is the ncessary, no othere better way to handle it.

Have a TodoList component, every time types in NewTodo input fields, will trigger the re-rendering for all components.

import React, { useState, useContext, useCallback } from "react";
import NewTodo from "./NewTodo";
import TodoItem from "./TodoItem5";
import { Container, List } from "./Styled";
import About from "./About";
import { useTodosWithLocalStorage, useKeyDown } from "./hooks";
import { useTitle as useDocumentTitle } from "react-use";
import ThemeContext from "./ThemeContext";

const incompleteTodoCount = todos =>
  todos.reduce((memo, todo) => (!todo.completed ? memo + 1 : memo), 0);

export default function TodoList() {
  const [newTodo, updateNewTodo] = useState("");
  const [todos, dispatch] = useTodosWithLocalStorage([]);
  const inCompleteCount = incompleteTodoCount(todos);
  const title = inCompleteCount ? `Todos (${inCompleteCount})` : "Todos";
  useDocumentTitle(title);
  let [showAbout, setShowAbout] = useKeyDown(
    { "?": true, Escape: false },
    false
  );
  const handleNewSubmit = e => {
    e.preventDefault();
    dispatch({ type: "ADD_TODO", text: newTodo });
    updateNewTodo("");
  };
  const theme = useContext(ThemeContext);

  return (
    <Container todos={todos}>
      <NewTodo
        onSubmit={handleNewSubmit}
        value={newTodo}
        onChange={e => updateNewTodo(e.target.value)}
      />
      {!!todos.length && (
        <List theme={theme}>
          {todos.map(todo => (
            <TodoItem
              key={todo.id}
              todo={todo}
              onChange={id => dispatch({ type: "TOGGLE_TODO", id })}
              onDelete={id => dispatch({ type: "DELETE_TODO", id })}
            />
          ))}
        </List>
      )}
      <About isOpen={showAbout} onClose={() => setShowAbout(false)} />
    </Container>
  );
}

The way to solve the problem is

1. For every callback:

<TodoItem
    onChange={id => dispatch({ type: "TOGGLE_TODO", id })}
    onDelete={id => dispatch({ type: "DELETE_TODO", id })}
/>

<About isOpen={showAbout} onClose={() => setShowAbout(false)} />

We should replace with useCallback hooks:

  const handleChange = useCallback(
    id => dispatch({ type: "TOGGLE_TODO", id }),
    []
  );
  const handleDelete = useCallback(
    id => dispatch({ type: "DELETE_TODO", id }),
    []
  );

  const handleClose = userCallback(
    () => setShowAbout(false), []
  )
      {!!todos.length && (
        <List theme={theme}>
          {todos.map(todo => (
            <TodoItem
              key={todo.id}
              todo={todo}
              onChange={handleChange}
              onDelete={handleDelete}
            />
          ))}
        </List>
      )}
      <About isOpen={showAbout} onClose={handleClose} />

This helps to reduce some extra re-rendering.

2. Using Reac.memo for function component:

import React, { useContext } from "react";
import Checkbox from "./Checkbox";
import ThemeContext from "./ThemeContext";
import { Button, Item } from "./Styled";

const TodoItem = React.memo(({ todo, onChange, onDelete }) => {
  console.log("TodoItem5", { todo, onChange, onDelete });
  const theme = useContext(ThemeContext);
  return (
    <Item key={todo.id} theme={theme}>
      <Checkbox
        id={todo.id}
        label={todo.text}
        checked={todo.completed}
        onChange={onChange.bind(this, todo.id)}
      />
      <Button onClick={onDelete.bind(this, todo.id)} theme={theme}>
        x
      </Button>
    </Item>
  );
});

export default TodoItem;
import React from "react";
import styled from "react-emotion";

import { Dialog } from "@reach/dialog";

...

export default React.memo(function TodoItem({ isOpen, onClose }) {
  return (
    <Dialog isOpen={isOpen}>
      ...
    </Dialog>
  );
});

Assume that every times I should wrap function component with React.memo() and use useCallback whenever necessary.

原文地址:https://www.cnblogs.com/Answer1215/p/10432142.html

时间: 2024-08-01 15:31:31

[React] Preventing extra re-rendering with function component by using React.memo and useCallback的相关文章

React 组件之 Component PureComponent Function Component

Virtual DOM , 通过高效的Diff算法对变化的部分首尾两端做批量更新,所有的比较都是浅比较shallowEqual.谁都玩不起深比较,facebook自己都做不到~ Component :一定要配套使用shouldComponentUpdate , 否则不管props or state是否更新组件一定更新 pureComponent :当组件的props和state不变时,组件是不更新的.仅仅只需要替换component => pureComponent,零投入超高回报 functi

[React] Preview and edit a component live with React Live

In this lesson we'll use React Live to preview and edit a component directly in the browser. React Live is a great tool for rendering interactive documentation or any place you would like to demonstrate a React component with a live preview and editi

精读《Function Component 入门》

1. 引言 如果你在使用 React 16,可以尝试 Function Component 风格,享受更大的灵活性.但在尝试之前,最好先阅读本文,对 Function Component 的思维模式有一个初步认识,防止因思维模式不同步造成的困扰. 2. 精读 什么是 Function Component? Function Component 就是以 Function 的形式创建的 React 组件: function App() { return ( <div> <p>App&l

编译依赖于React Native0.46.4的React Native IOS工程时,出现错误“fatal error: &#39;React/RCTEventEmitter.h&#39; file not found”

我的环境: WebStorm 2017.2Build #WS-172.3317.70, built on July 14, 2017 JRE: 1.8.0_152-release-915-b5 x86_64JVM: OpenJDK 64-Bit Server VM by JetBrains s.r.o Mac OS X 10.12.6 Xcode8.3.3(8E3004b) 网上搜索,可以解决我的问题的网址:https://stackoverflow.com/questions/41663002

React Native -- The Life-Cycle of a Composite Component

/** * ------------------ The Life-Cycle of a Composite Component ------------------ * * - constructor: Initialization of state. The instance is now retained. * - componentWillMount * - render * - [children's constructors] * - [children's componentWil

[React] Update Component State in React With Ramda Lenses

In this lesson, we'll refactor a React component to use Ramda lenses to update our component state. We'll create a lens to focus on the property we want to target and use over to apply the existing state value to a utility function and we'll get back

[React] Cleanly Map Over A Stateless Functional Component with a Higher Order Component

In this lesson we'll create a Higher Order Component (HOC) that takes care of the key property that React looks for when using map to create elements from a list. This HOC will allow us to wrap any component and it will take care of placing the keypr

[React] Create component variations in React with styled-components and &quot;extend&quot;

In this lesson, we extend the styles of a base button component to create multiple variations of buttons, using "extend". We can then modify the base styles in one place, and have all button types updated. import React from "react"; im

React的设计思想——理解JSX和Component

基于HTML的前端界面开发正变得越来越复杂,其本质问题基本都可以归结于如何将来自于服务器端或者用户输入的动态数据高效的反映到复杂的用户界面上.而来自Facebook的React框架正是完全面向此问题的一个解决方案.React带来了很多开创性的思路来构建前端界面,虽然选择React的最重要原因之一是性能,但是相关技术背后的设计思想更值得我们去思考. React项目经理Tom Occhino曾经阐述React诞生的初衷,他提到React最大的价值究竟是什么?是高性能虚拟DOM.服务器端Render.