使用 React Hooks 重构类组件的示例详解

目录
  • 1. 管理和更新组件状态
  • 2. 状态更新后的操作
  • 3. 获取数据
  • 4. 卸载组件时清理副作用
  • 5.  防止组件重新渲染
  • 6. Context API
  • 7. 跨重新渲染保留值
  • 8. 如何向父组件传递状态和方法?
  • 9. 小结

最初,在 React 中可以使用 createClass 来创建组件,后来被类组件所取代。在 React 16.8 版本中,新增的 Hooks 功能彻底改变了我们编写 React 程序的方式,使用 Hooks 可以编写更简洁、更清晰的代码,并为创建可重用的有状态逻辑提供了更好的模式。

许多公司和开发人员都放弃了类组件转而使用 Hooks。而许多旧的的React 项目仍然在使用类组件。更重要的是,在类组件中有 Error Boundaries,而函数组件中是无法使用 Error Boundaries 的。

本文就来通过一些常见示例看看如何使用 React Hooks 来重构类组件。

1. 管理和更新组件状态

状态管理是几乎所有 React 应用中最重要的部分,React 基于 state 和 props 渲染组件。每当它们发生变化时,组件就会重新渲染,并且 DOM 也会相应地更新。下面来看一个计数器的例子,它包含一个计数状态以及两个更新它的地方:

import { Component } from "react";
class ManagingStateClass extends Component {
  state = {
    counter: 0,
  };
  increment = () => {
    this.setState(prevState => {
      return {
        counter: prevState.counter + 1,
      };
    });
  };
  decrement = () => {
    this.setState(prevState => {
      return {
        counter: prevState.counter - 1,
      };
    });
  };

  render() {
    return (
      <div>
        <div>Count: {this.state.counter}</div>
        <div>
          <button onClick={this.increment}>Increment</button>
          <button onClick={this.decrement}>Decrement</button>
        </div>
      </div>
    );
  }
}
export default ManagingStateClass;

下面来使用 Hooks 实现这个计数器组件:

import { useState } from "react";
const ManagingStateHooks = () => {
  const [counter, setCounter] = useState(0);
  const increment = () => setCounter(counter => counter + 1);
  const decrement = () => setCounter(counter => counter - 1);
  return (
    <div>
      <div>Count: {counter}</div>
      <div>
        <button onClick={increment}>Increment</button>
        <button onClick={decrement}>Decrement</button>
      </div>
    </div>
  );
};
export default ManagingStateHooks;

该组件是一个返回 JSX 的函数,使用 useState​ hook来管理计算器的状态。它返回一个包含两个值的数组:第一个值为状态,第二个值为更新函数。并且使用 setCounter​ 来更新程序的increment和decrement函数。

2. 状态更新后的操作

在某些情况下,我们可能需要在状态更新时执行某些操作。在类组件中,我们通常会在componentDidUpdate 生命周期中实现该操作。

import { Component } from "react";
class StateChangesClass extends Component {
  state = {
    counter: 0,
  };
  componentDidUpdate(prevProps, prevState) {
    localStorage.setItem("counter", this.state.counter);
  }
  increment = () => {
    this.setState(prevState => {
      return {
        counter: prevState.counter + 1,
      };
    });
  };

  decrement = () => {
    this.setState(prevState => {
      return {
        counter: prevState.counter - 1,
      };
    });
  };
  render() {
    return (
      <div>
        <div>Count: {this.state.counter}</div>
        <div>
          <button onClick={this.increment}>Increment</button>
          <button onClick={this.decrement}>Decrement</button>
        </div>
      </div>
    );
  }
}
export default StateChangesClass;

当状态发生变化时,我们将新的计数器值保存在 localStorage​ 中。在函数组件中,我们可以通过使用 useEffect hook 来实现相同的功能。

import { useState, useEffect } from "react";
const StateChangesHooks = () => {
  const [counter, setCounter] = useState(0);
  const increment = () => setCounter(counter => counter + 1);
  const decrement = () => setCounter(counter => counter - 1);
  useEffect(() => {
    localStorage.setItem("counter", counter);
  }, [counter]);

  return (
    <div>
      <div>Count: {counter}</div>
      <div>
        <button onClick={increment}>Increment</button>
        <button onClick={decrement}>Decrement</button>
      </div>
    </div>
  );
};
export default StateChangesHooks;

这个 useEffect​ hook 有两个参数,第一个参数是回调函数,第二个参数是依赖数组。在组件挂载时,这个 hook​ 至少会执行一次。然后,仅在依赖数组内的任何值发生变化时都会触发第一个参数传入的回调函数。如果依赖数组为空,则回调函数只会执行一次。在上面的例子中,每当 counter​ 发生变化时,都会触发将 counter​ 保存在 localStorage 中的回调函数。

3. 获取数据

在类组件中,通过会在componentDidMount生命周期中初始化一个 API 请求来获取数据。下面来看一个获取并显示帖子列表的组件:

import { Component } from "react";
class FetchingDataClass extends Component {
  state = {
    posts: [],
  };
  componentDidMount() {
    this.fetchPosts();
  }
  fetchPosts = async () => {
    const response = await fetch("https://jsonplaceholder.typicode.com/posts");
    const data = await response.json();
    this.setState({
      posts: data.slice(0, 10),
    });
  };

  render() {
    return (
      <div>
        {this.state.posts.map(post => {
          return <div key={post.id}>{post.title}</div>;
        })}
      </div>
    );
  }
}
export default FetchingDataClass

有了 hooks,就可以使用useEffect​来实现上述功能。它会在第一次挂载之后执行一次,然后在任何依赖发生变化时再次触发。useEffect​ 允许我们传入一个空依赖数组作为第二个参数来确保只执行一次effect的回调函数。

import { useState, useEffect } from "react";
const FetchingDataHooks = () => {
  const [posts, setPosts] = useState([]);
  const fetchPosts = async () => {
    const response = await fetch("https://jsonplaceholder.typicode.com/posts");
    const data = await response.json();
    setPosts(data.slice(0, 10));
  };
  useEffect(() => {
    fetchPosts();
  }, []);

  return (
    <div>
      {posts.map(post => {
         return <div key={post.id}>{post.title}</div>;
      })}
    </div>
  );
};
export default FetchingDataHooks;

4. 卸载组件时清理副作用

在卸载组件时清理副作用是非常重要的,否则可能会导致内存泄露。例如,在一个组件中,我们想要监听一个事件,比如resize​或者scroll​,并根据窗口大小或滚动的位置来做一些事情。下面来看一个类组件的例子,它会监听 resize​ 事件,然后更新浏览器窗口的宽度和高度的状态。事件监听器在 componentWillUnmount 生命周期中被移除。

import { Component } from "react";
class CleanupClass extends Component {
  state = {
    width: window.innerWidth,
    height: window.innerHeight,
  };
  componentDidMount() {
    window.addEventListener("resize", this.updateWindowSize, {
      passive: true,
    });
  }
  componentWillUnmount() {
    window.removeEventListener("resize", this.updateWindowSize, {
      passive: true,
    });
  }

  updateWindowSize = () => {
    this.setState({
      width: window.innerWidth,
      height: window.innerHeight,
    });
  };
  render() {
    return (
      <div>
        Window: {this.state.width} x {this.state.height}
      </div>
    );
  }
}
export default CleanupClass;

在 useEffect​ 中,我们可以在回调函数中返回一个函数来执行清理操作,卸载组件时会调用此函数。下面,首先来定义一个 updateWindowSize​ 函数,然后在 useEffect​ 中添加 resize 事件监听器。接下来返回一个匿名箭头函数,它将用来移除监听器。

import { useState, useEffect } from "react";
const CleanupHooks = () => {
  const [width, setWidth] = useState(window.innerWidth);
  const [height, setHeight] = useState(window.innerHeight);
  useEffect(() => {
    const updateWindowSize = () => {
      setWidth(window.innerWidth);
      setHeight(window.innerHeight);
    };
    window.addEventListener("resize", updateWindowSize, {
      passive: true,
    });
    return () => {
      window.removeEventListener("resize", this.updateWindowSize, {
        passive: true,
      });
    };
  }, []);

  return (
      <div>
        Window: {this.state.width} x {this.state.height}
      </div>
  );
};
export default CleanupHooks;

5.  防止组件重新渲染

React 非常快,通常我们不必担心过早的优化。但是,在某些情况下,优化组件并确保它们不会过于频繁地重新渲染是很有必要的。

例如,减少类组件重新渲染的常用方法是使用 PureComponent​ 或者 shouldComponentUpdate​ 生命周期。下面例子中有两个类组件(父组件和子组件),父组件有两个状态值:counter​ 和 fruit​。子组件只在父组件的 fruit​ 发生变化时重新渲染。所以,使用 shouldComponentUpdat​e 生命周期来检查 fruit 属性是否改变。如果相同,则子组件不会重新渲染。

父组件:

import { Component } from "react";
import PreventRerenderClass from "./PreventRerenderClass.jsx";
function randomInteger(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
const fruits = ["banana", "orange", "apple", "kiwi", "mango"];
class PreventRerenderExample extends Component {
  state = {
    fruit: null,
    counter: 0,
  };
  pickFruit = () => {
    const fruitIdx = randomInteger(0, fruits.length - 1);
    const nextFruit = fruits[fruitIdx];
    this.setState({
      fruit: nextFruit,
    });
  };
  componentDidMount() {
    this.pickFruit();
  }
  render() {
    return (
      <div>
        <h3>
          Current fruit: {this.state.fruit} | counter: {this.state.counter}
        </h3>
        <button onClick={this.pickFruit}>挑一个水果</button>
        <button
          onClick={() =>
            this.setState(({ counter }) => ({
              counter: counter + 1,
            }))
          }
        >
          Increment
        </button>
        <button
          onClick={() =>
            this.setState(({ counter }) => ({ counter: counter - 1 }))
          }
        >
          Decrement
        </button>
        <div className="section">
          <PreventRerenderClass fruit={this.state.fruit} />
        </div>
      </div>
    );
  }
}
export default PreventRerenderExample;

子组件:

import { Component } from "react";
class PreventRerenderClass extends Component {
  shouldComponentUpdate(nextProps, nextState) {
    return this.props.fruit !== nextProps.fruit;
  }
  render() {
    return (
      <div>
        <p>Fruit: {this.props.fruit}</p>
      </div>
    );
  }
}
export default PreventRerenderClass;

随着 hooks 的引入,我们得到了一个新的高阶组件,称为 memo。它可用于优化性能并防止函数组件重新渲染。下面来看看它是怎么用的。

父组件:

import { useState, useEffect } from "react";
import PreventRerenderHooks from "./PreventRerenderHooks.jsx";
function randomInteger(min, max) {
  return Math.floor(Math.random() * (max - min + 1)) + min;
}
const fruits = ["banana", "orange", "apple", "kiwi", "mango"];
const PreventRerenderExample = () => {
  const [fruit, setFruit] = useState(null);
  const [counter, setCounter] = useState(0);
  const pickFruit = () => {
    const fruitIdx = randomInteger(0, fruits.length - 1);
    const nextFruit = fruits[fruitIdx];
    setFruit(nextFruit);
  };
  useEffect(() => {
    pickFruit();
  }, []);
  return (
    <div>
      <h3>
        Current fruit: {fruit} | counter: {counter}
      </h3>
      <button onClick={pickFruit}>挑一个水果</button>
      <button onClick={() => setCounter(counter => counter + 1)}>
        Increment
      </button>
      <button onClick={() => setCounter(counter => counter - 1)}>
        Decrement
      </button>
      <div className="section">
        <PreventRerenderHooks fruit={fruit} />
      </div>
    </div>
  );
};
export default PreventRerenderExample;

子组件:

import { memo } from "react";
const PreventRerenderHooks = props => {
  return (
    <div>
      <p>Fruit: {props.fruit}</p>
    </div>
  );
};
export default memo(PreventRerenderHooks);

PreventRerenderHooks​ 组件使用 memo​ 组件包装,并且仅在 props 中的 fruit 发生变化时发挥重新渲染。需要注意,memo组件执行的是浅比较,因此如果需要更好地控制memo​组件何时重新渲染,可以提供自己的函数来执行 props 比较。

import { memo } from "react";
const PreventRerenderHooks = props => {
  return (
    <div>
      <p>Fruit: {props.fruit}</p>
    </div>
  );
};
export default memo(PreventRerenderHooks, (prevProps, nextProps) => {
  return prevProps.fruit !== nextProps.fruit
});

6. Context API

Context API 是一个很好用的工具,可以为组件层次结构中不同级别的组件提供值。可以使用 React 提供的 createContext​ 方法创建新的上下文。先来看一个在类组件中使用 context 的例子。

Context Provider:

import { createContext } from "react";

export const UserContext = createContext();
export const UserActionsContext = createContext();

在父组件中,向消费者提供了 UserContext​ 和 UserActionsContext。

import { Component, createContext } from "react";
import ContextApiClassConsumer from "./ContextApiClassConsumer.jsx";
import { UserContext, UserActionsContext } from "./userContext.js";
class ContextApiHooksProvider extends Component {
  state = {
    user: {
      name: "Class",
    },
  };
  setUser = user => this.setState({ user });
  render() {
    return (
      <UserContext.Provider value={this.state.user}>
        <UserActionsContext.Provider value={this.setUser}>
          <ContextApiClassConsumer />
        </UserActionsContext.Provider>
      </UserContext.Provider>
    );
  }
}
export default ContextApiHooksProvider;

这里 ContextApiClassConsumer​ 组件就可以获取到父组件提供的user和setUser。

Context Consumer:

import { Component } from "react";
import { UserContext, UserActionsContext } from "./userContext.js";
class ContextApiClassConsumer extends Component {
  render() {
    return (
      <UserContext.Consumer>
        {user => (
          <UserActionsContext.Consumer>
            {setUser => (
              <div>
                <input
                  type="text"
                  value={user.name}
                  onChange={e =>
                    setUser({
                      name: e.target.value,
                    })
                  }
                />
              </div>
            )}
          </UserActionsContext.Consumer>
        )}
      </UserContext.Consumer>
    );
  }
}
export default ContextApiClassConsumer;

在上面的例子中,UserContext.Consumer​ 组件的子函数接收 user 状态,UserActionsContext.Consumer​ 的子函数接收 setUser 方法。

使用 Hooks 实现和上面的代码非常类似,但是会更简洁。同样,我们使用 UserContext.Provider​ 和 UserActionsContext.Provider​ 组件来提供 user​ 状态和 setUser 方法。

Context Provider:

import { useState } from "react";
import ContextApiHooksConsumer from "./ContextApiHooksConsumer.jsx";
import { UserContext, UserActionsContext } from "./userContext.js";
const ContextApiHooksProvider = () => {
  const [user, setUser] = useState({
    name: "Hooks",
  });
  return (
    <UserContext.Provider value={user}>
      <UserActionsContext.Provider value={setUser}>
        <ContextApiHooksConsumer />
      </UserActionsContext.Provider>
    </UserContext.Provider>
  );
};
export default ContextApiHooksProvider;

在函数组件中,我们可以像在类组件中一样使用 context​,但是,hooks 中有一种更简洁的方法,我们可以利用 useContext​ hook 来访问 context 值。

Context Consumer:

import { useContext } from "react";
import { UserContext, UserActionsContext } from "./userContext.js";
const ContextApiHooksConsumer = () => {
  const user = useContext(UserContext);
  const setUser = useContext(UserActionsContext);
  return (
    <div>
      <input
        type="text"
        value={user.name}
        onChange={e =>
          setUser({
            name: e.target.value,
          })
        }
      />
    </div>
  );
};
export default ContextApiHooksConsumer;

7. 跨重新渲染保留值

在某些情况下,我们可能需要再组件中存储一些数据。但是不希望将其存储在状态中,因为 UI 不以任何方式依赖这些数据。

例如,我们可能会保存一些希望稍后包含在 API 请求中的元数据。这在类组件中很容易实现,只需为类分配一个新属性即可。

import { Component } from "react";
class PreservingValuesClass extends Component {
  state = {
    counter: 0,
  };
  componentDidMount() {
    this.valueToPreserve = Math.random();
  }
  showValue = () => {
    alert(this.valueToPreserve);
  };
  increment = () => this.setState(({ counter }) => ({ counter: counter + 1 }));
  render() {
    return (
      <div>
        <p>Counter: {this.state.counter}</p>
        <button onClick={this.increment}>Increment</button>
        <button onClick={this.showValue}>Show</button>
      </div>
    );
  }
}
export default PreservingValuesClass;

在这个例子中,当组件被挂载时,我们在 valueToPreserve​ 属性上分配了一个动态随机数。除此之外,还有 increment 方法来强制重新渲染,但是Show按钮时会弹窗显示保留的值。

这在类组件中很容易实现,但是在函数组件中就没那么简单了。这是因为,任何时候函数组件的重新渲染都会导致函数中的所有内容重新执行。这意味着如果我们有这样的组件:

const MyComponent = props => {
  const valueToPreserve = Math.random()
  // ...
}

组件每次重新渲染时都会重新调用 Math.random() 方法,因此创建的第一个值将丢失。

避免此问题的一种方法是将变量移到组件之外。但是,这是行不通的,因为如果该组件被多次使用,则该值会将被它们中的每一个覆盖。

恰好,React 提供了一个非常适合这个用例的 hook。我们可以通过使用 useRef hook 来保留函数组件中重新渲染的值。

import { useState, useRef, useEffect } from "react";
const PreserveValuesHooks = props => {
  const valueToPreserve = useRef(null);
  const [counter, setCounter] = useState(0);
  const increment = () => setCounter(counter => counter + 1);
  const showValue = () => {
    alert(valueToPreserve.current);
  };
  useEffect(() => {
    valueToPreserve.current = Math.random();
  }, []);
  return (
    <div>
      <p>Counter: {counter}</p>
      <button onClick={increment}>Increment</button>
      <button onClick={showValue}>Show value</button>
    </div>
  );
};
export default PreserveValuesHooks;

valueToPreserve 是一个初始值为 null​ 的 ref​。但是,它后来在 useEffect 中更改为我们想要保留的随机数。

8. 如何向父组件传递状态和方法?

尽管我们不应该经常访问子组件的状态和属性,但是在某些情况下它可能会很有用。例如,我们想要重置某些组件的状态或者访问它的状态。我们需要创建一个 Ref,可以在其中存储对想要访问的子组件的引用。在类组件中,可以使用 createRef​ 方法,然后将该 ref 传递给子组件。

父组件:

import { Component, createRef } from "react";
import ExposePropertiesClassChild from "./ExposePropertiessClassChild";
class ExposePropertiesClassParent extends Component {
  constructor(props) {
    super(props);
    this.childRef = createRef();
  }
  showValues = () => {
    const counter = this.childRef.current.state.counter;
    const multipliedCounter = this.childRef.current.getMultipliedCounter();
    alert(`
      counter: ${counter}
      multipliedCounter: ${multipliedCounter}
    `);
  };
  increment = () => this.setState(({ counter }) => ({ counter: counter + 1 }));
  render() {
    return (
      <div>
        <button onClick={this.showValues}>Show</button>
        <ExposePropertiesClassChild ref={this.childRef} />
      </div>
    );
  }
}
export default ExposePropertiesClassParent;

子组件:

import { Component } from "react";
class ExposePropertiesClassChild extends Component {
  state = {
    counter: 0,
  };
  getMultipliedCounter = () => {
    return this.state.counter * 2;
  };
  increment = () => this.setState(({ counter }) => ({ counter: counter + 1 }));
  render() {
    return (
      <div>
        <p>Counter: {this.state.counter}</p>
        <button onClick={this.increment}>Increment</button>
      </div>
    );
  }
}
export default ExposePropertiesClassChild;

要访问子组件的属性,只需要在父组件中创建一个 ref 并传递它。现在,让我们看看如何使用函数组件和 hook 来实现相同的目标。

父组件:

import { useRef } from "react";
import ExposePropertiesHooksChild from "./ExposePropertiesHooksChild";

const ExposePropertiesHooksParent = props => {
  const childRef = useRef(null);

  const showValues = () => {
    const counter = childRef.current.counter;
    const multipliedCounter = childRef.current.getMultipliedCounter();
    alert(`
      counter: ${counter}
      multipliedCounter: ${multipliedCounter}
    `);
  };

  return (
    <div>
      <button onClick={showValues}>Show</button>
      <ExposePropertiesHooksChild ref={childRef} />
    </div>
  );
};

export default ExposePropertiesHooksParent;

在父组件中,我们使用 useRef​ hook 来存储对子组件的引用。然后在 showValues 函数中访问 childRef 的值。可以看到,这里与类组件中的实现非常相似。

子组件:

import { useState, useImperativeHandle, forwardRef } from "react";

const ExposePropertiesHooksChild = (props, ref) => {
  const [counter, setCounter] = useState(0);

  const increment = () => setCounter(counter => counter + 1);

  useImperativeHandle(ref, () => {
    return {
      counter,
      getMultipliedCounter: () => counter * 2,
    };
  });

  return (
    <div>
      <p>Counter: {counter}</p>
      <button onClick={increment}>Increment</button>
    </div>
  );
};

export default forwardRef(ExposePropertiesHooksChild);

forwardRef​ 将从父组件传递的 ref​ 转发到组件,而 useImperativeHandle 指定了父组件应该可以访问的内容。

9. 小结

通过这篇文章,相信你对使用Hooks(函数组件)来重构类组件有了一定了解。Hooks 的出现使得 React 代码更加简洁,并且带来了更好的状态逻辑可重用性。在开始编写 Hooks 之前,建议先阅读 React Hooks 的官方文档,因为在编写时需要遵循某些规则,例如不要改变 Hooks 的调用顺序。

到此这篇关于如何使用 React Hooks 重构类组件?的文章就介绍到这了,更多相关React Hooks 重构类组件内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • 为react组件库添加typescript类型提示的方法

    以我自己的组件react-better-countdown为例, 首先在package.json里面添加types: types/index.d.ts, , 然后文件目录上添加对应文件夹和文件, 最后是index.d.ts文件的编写,具体看代码: import * as React from 'react'; interface CountdownProps { count?: number; dayText?: string | React.ReactElement; hourText?: s

  • React函数式组件与类组件的不同你知道吗

    目录 区别 其他区别 总结 区别 区别 函数组件 类组件 生命周期 无 有 this 无 有 state 无 有 改变state React Hooks:useState this.setState() 性能 高(不用实例化) 低(需要实例化) 其他区别 ProfilePageClass.js import React from 'react'; class ProfilePageClass extends React.Component { showMessage = () => { aler

  • React函数组件与类组件使用及优劣对比

    目录 一.类组件的问题 原因一.因为this带来的问题: 问题描述 问题解析 原因二.类组件代码量比函数组件多: 原因三.类组件过于臃肿不易拆分: 二.函数组件的问题 挂载阶段:getDerviedStateFromProps VS 无 挂载阶段:UNSAFE_componentWillMount VS 无 挂载阶段:componentDidMount VS useEffect render: 生命周期,更新阶段:UNSAFE_componentWillRerciveProps VS 无 生命周

  • React通过父组件传递类名给子组件的实现方法

    React 教程 React 是一个用于构建用户界面的 JAVASCRIPT 库. React主要用于构建UI,很多人认为 React 是 MVC 中的 V(视图). React 起源于 Facebook 的内部项目,用来架设 Instagram 的网站,并于 2013 年 5 月开源. React 拥有较高的性能,代码逻辑非常简单,越来越多的人已开始关注和使用它. React 特点 1.声明式设计 −React采用声明范式,可以轻松描述应用. 2.高效 −React通过对DOM的模拟,最大限度

  • React 函数式组件和类式组件详情

    目录 前言 1. 函数式组件 2. 类式组件 前言 React 是 组件化的 的 JS 库,组件化 也是 React 的核心思想.使用 React 可以构建管理自身状态的封装组件,然后对其组合以构成复杂的 UI.那么什么是组件呢? 组件是用来实现局部功能效果的代码和资源的集合,包括 html / css / js/ image 等,组件的作用是 简化代码.复用代码.提高运行效率. React 里主要有两种类型的组件: 函数式组件 => 基于函数: 类式组件 => 基于类: 1. 函数式组件 函

  • 深入理解react 组件类型及使用场景

    函数组件 vs 类组件 函数组件(Functional Component )和类组件(Class Component),划分依据是根据组件的定义方式.函数组件使用函数定义组件,类组件使用ES6 class定义组件 // 函数组件 function Welcome(props) { return <h1>Hello, {props.name}</h1>; } // 类组件 class Welcome extends React.Component { render() { retu

  • React函数式组件的性能优化思路详解

    优化思路 主要优化的方向有2个: 减少重新 render 的次数.因为在 React 里最重(花时间最长)的一块就是 reconction(简单的可以理解为 diff),如果不 render,就不会 reconction. 减少计算的量.主要是减少重复计算,对于函数式组件来说,每次 render 都会重新从头开始执行函数调用. 在使用类组件的时候,使用的 React 优化 API 主要是:shouldComponentUpdate和 PureComponent 那么在函数式组件中,我们怎么做性能

  • 使用 React Hooks 重构类组件的示例详解

    目录 1. 管理和更新组件状态 2. 状态更新后的操作 3. 获取数据 4. 卸载组件时清理副作用 5.  防止组件重新渲染 6. Context API 7. 跨重新渲染保留值 8. 如何向父组件传递状态和方法? 9. 小结 最初,在 React 中可以使用 createClass 来创建组件,后来被类组件所取代.在 React 16.8 版本中,新增的 Hooks 功能彻底改变了我们编写 React 程序的方式,使用 Hooks 可以编写更简洁.更清晰的代码,并为创建可重用的有状态逻辑提供了

  • React 模式之纯组件使用示例详解

    目录 什么是纯组件 纯组件解决了什么问题 怎么使用纯组件 CC: shouldComponentUpdate() 和 React.PureComponent FC: React.memo() 你可能并不需要纯组件 什么是纯组件 纯组件(Pure Component)这概念衍生自纯函数.纯函数指的是返回结果只依赖于传入的参数,且对函数作用域外没有副作用的函数.这种函数在相同参数下,返回结果是不变的.纯函数的返回值能被安全地缓存起来,在下次调用时,跳过函数执行,直接读取缓存.因为函数没有外部副作用,

  • React之错误边界 Error Boundaries示例详解

    目录 引言 注意 实现 错误边界应该放置在哪? 未捕获错误(Uncaught Errors)该如何处理? 注意:自 React 15 的命名更改 引言 过去,组件内的代码异常会导致 React 的内部状态被破坏,产生可能无法追踪的错误.但 React 并没有提供一种优雅处理这些错误的方式,也无法从错误中恢复. 默认情况下,若一个组件在渲染期间(render)发生错误,会导致整个组件树全部被卸载,这当然不是我们期望的结果. 部分组件的错误不应该导致整个应用崩溃.为了解决这个问题,React 16

  • flutter text组件使用示例详解

    目录 正文 Text组件 Text组件构造器上的主要属性 正文 flutter组件的实现参考了react的设计理念,界面上所有的内容都是由组件构成,同时也有状态组件和无状态组件之分,这里简单介绍最基本的组件. 在组件代码的书写方式上,web端开发的样式主要有由css进行控制,而客户端开发根据使用的技术栈不同,写法也稍微有些不同:ReactNative的写法和web比较类似,但是ReactNative是使用StyleSheet.create()方法创建样式对象,以内联的方式进行书写. import

  • React路由拦截模式及withRouter示例详解

    目录 一.路由拦截 二.路由模式 三.withRouter 一.路由拦截 在前面两篇 路由博客基础上,我们将ReactRouter.js的我的profile路由设置成路由拦截的: <Route path="/profile" render={() => isAuth() ? <Profile/> : <Redirect to="/login"></Redirect> }></Route> 新建Logi

  • react中使用antd及immutable示例详解

    目录 一.react中使用antd组件库 二.Immutable 2.1 深拷贝和浅拷贝的关系 2.2 immutable优化性能方式 2.3 immutable的Map使用 2.4 immutable的List使用 2.5 实际场景formJS 三.redux中使用immutable 一.react中使用antd组件库 运行命令create-react-app antd-react创建新项目: 运行命令npm i antd安装: 使用: import React from 'react' im

  • React特征学习之Form格式示例详解

    目录 Form 样式 React hook Form 样式 首先来看一个简单Form, 式样如下 import * as React from 'react'; const LoginForm = () => { return ( <form> <div> // Notice: 这里要用htmlFor,相当于id <label htmlFor="email">Email</label> <input id="emai

  • React.memo函数中的参数示例详解

    目录 React.memo?这是个啥? React.memo的第一个参数 父组件 子组件 React.memo优化 React.memo的第二个参数 父组件 子组件 React.memo优化 父组件 子组件 小结 React.memo?这是个啥? 按照官方文档的解释: 如果你的函数组件在给定相同 props 的情况下渲染相同的结果,那么你可以通过将其包装在 React.memo 中调用,以此通过记忆组件渲染结果的方式来提高组件的性能表现.这意味着在这种情况下,React 将跳过渲染组件的操作并直

  • python编程普通及类和静态方法示例详解

    目录 前言 运行环境 普通方法 类方法 静态方法 前言 本文主要讲述了python类中的三类常用方法,普通方法.类方法和静态方法.  本文主要参考了https://youtu.be/rq8cL2XMM5M,强烈推荐一看这个系列的所有视频. 运行环境 import sys sys.version 结果为 '3.6.1 |Anaconda 4.4.0 (64-bit)| (default, May 11 2017, 13:25:24) [MSC v.1900 64 bit (AMD64)]' 普通方

  • Java中枚举类的用法示例详解

    目录 1.引入枚举类 2.实现枚举类 3.枚举类的使用注意事项 4.枚举的常用方法 5.enum细节 1.引入枚举类 Java 枚举是一个特殊的类,一般表示一组常量,比如一年的 4 个季节,一个年的 12 个月份,一个星期的 7 天,方向有东南西北等. Java 枚举类使用 enum 关键字来定义,各个常量使用逗号 , 来分割. 示例: enum Color { RED, GREEN, BLUE; } 2.实现枚举类 接下来我们来看一个一个简单的DEMO示例: /** * java枚举 */ p

随机推荐