11_react hooks

1. What is Hook?
  • Hooks are a new feature in React 16.8. You can use state and other React features without writing a class.
  • There are no plans to remove classes from React. Hooks can work with existing code, and they can be used incrementally.
2. Hook usage rules?

Hooks are JavaScript functions, but there are two additional rules for using them:

  • Hook can only be called at the outermost layer of the function. Do not call in loops, conditionals, or subfunctions.
  • Hooks can only be called in React's functional components. Do not call within other JavaScript functions. (There is another place where Hook can be called - in a custom Hook.)
3. useState()

Add internal state on React function components.

import React, {
    
     useState } from "react";

function Example() {
    
    
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>You clicked {
    
    count} times</p>
      <button onClick={
    
    () => setCount(count + 1)}>Click me</button>
    </div>
  );
}
4. useEffect()
  • useEffect adds the ability to manipulate side effects to function components. You can think of useEffect as a combination of the three functions componentDidMount, componentDidUpdate and componentWillUnmount.
  • Tells React that a component needs to perform certain actions after rendering. React guarantees that the DOM has been updated every time the effect is run.
  1. Effects that need to be cleared (such as sending network requests, manually changing DOM, recording logs)
useEffect(() => {
    
    
  function handleStatusChange(status) {
    
    
    setIsOnline(status.isOnline);
  }

  ChatAPI.subscribeToFriendStatus(props.friend.id, handleStatusChange);
  return () => {
    
    
    ChatAPI.unsubscribeFromFriendStatus(props.friend.id, handleStatusChange);
  };
});
  1. Effects that do not need to be cleared (subscribe to external data sources)
useEffect(() => {
    
    
  document.title = `You clicked ${
      
      count} times`;
});
  1. Performance optimization by skipping Effects
useEffect(() => {
    
    
  document.title = `You clicked ${
      
      count} times`;
}, [count]); // 仅在 count 更改时更新。类似componentDidUpdate()。

useEffect(() => {
    
    
  document.title = `You clicked ${
      
      count} times`;
}, []); // 不依赖于 props 或 state 中的值,所以永远都不需要重复执行。类似componentDidMount()。
Five, custom hook

By customizing Hooks, component logic can be extracted into reusable functions.

  • Must start with use
  • Using the same Hook in two components will not share state
6. Additional hooks
  1. useContext
function B() {
    
    
  // 3. 通过Comsumer获取数据
  return (
    <div>
      <Context.Consumer>{
    
    (value) => <span>{
    
    value}</span>}</Context.Consumer>
    </div>
  );
  // 4. react16.8版本之后增加了hooks,可以使用hooks中的useContext来获取消费者
  import {
    
     useContext } from "react";
  const {
    
     name } = useContext(Context);
  // 直接这样定义就可以拿到consumer的值,省去了之前要定义在Consumer中才能使用。
}
  1. useReducer
const [state, dispatch] = useReducer(reducer, initialArg, init);

In some scenarios, useReducer is more suitable than useState, for example, the state logic is complex and contains multiple sub-values, or the next state depends on the previous state, etc.

const initialState = {
    
     count: 0 };

function reducer(state, action) {
    
    
  switch (action.type) {
    
    
    case "increment":
      return {
    
     count: state.count + 1 };
    case "decrement":
      return {
    
     count: state.count - 1 };
    default:
      throw new Error();
  }
}

function Counter() {
    
    
  const [state, dispatch] = useReducer(reducer, initialState);
  return (
    <>
      Count: {
    
    state.count}
      <button onClick={
    
    () => dispatch({
    
     type: "decrement" })}>-</button>
      <button onClick={
    
    () => dispatch({
    
     type: "increment" })}>+</button>
    </>
  );
}

If the return value of the Reducer Hook is the same as the current state, React will skip the rendering of child components and the execution of side effects. (React uses the Object.is comparison algorithm to compare state).

  1. useCallback
const memoizedCallback = useCallback(() => {
    
    
  doSomething(a, b);
}, [a, b]);
// 返回一个 memoized 回调函数。

Pass an inline callback function and an array of dependencies as parameters to useCallback, and it will return a memoized version of the callback function, the callback function 仅在某个依赖项改变时才会更新. It is useful when you pass callbacks to child components that are optimized and use reference equality to avoid unnecessary rendering (eg shouldComponentUpdate).

useCallback(fn, deps) 相当于 useMemo(() => fn, deps)。

  1. useMemo
    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
    returns a memoized value.
  • Passing a "create" function and an array of dependencies as parameters useMemowill only recalculate the memoized value when one of the dependencies changes. Helps avoid expensive calculations on every render.

  • The function passed to useMemo will be executed during rendering. Do not perform operations that have nothing to do with rendering in this function, such as side effects operations belong to the applicable scope of useEffect, not useMemo.

  • No dependencies array provided, useMemo 在每次渲染时都会计算新的值.

  1. useRef

  2. useImperativeHandle
    useImperativeHandle(ref, createHandle, [deps])
    useImperativeHandle allows you to use ref 自定义暴露给父组件的实例值. In most cases, imperative code like ref should be avoided. useImperativeHandle 应当与 forwardRef 一起使用:

function FancyInput(props, ref) {
    
    
  const inputRef = useRef();
  useImperativeHandle(ref, () => ({
    
    
    focus: () => {
    
    
      inputRef.current.focus();
    }
  }));
  return <input ref={
    
    inputRef} ... />;
}
FancyInput = forwardRef(FancyInput);

In this example, the rendered parent component can call inputRef.current.focus().

  1. The difference between useLayoutEffect
    and useEffect:
  • useEffect will be executed after the rendered content is updated to the DOM, and will not block the update of the DOM (commonly used) (asynchronous);
  • useLayoutEffect will be performed before the rendered content is updated to the DOM, which will block the DOM update (only used when it affects the rendering result) (synchronous).

Guess you like

Origin blog.csdn.net/weixin_42465316/article/details/129292195