react-hooks(更新中)

108 阅读3分钟

Hooks

useState

useState​ 是 React Hooks 中最常用的 hook 之一,它允许您在函数组件中使用状态。它接受一个初始状态值,并返回一个数组,其中包含当前状态和一个更新状态的函数。每次更新状态时,组件都会重新渲染。

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

参数说明:

  • initialState​:初始状态值。

返回值:

  • state​:当前状态值。
  • setState​:用于更新状态值的函数。
import React, { useState } from 'react';

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

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={handleClick}>Click me</button>
    </div>
  );
}

export default Counter;

详解:

  • 在函数组件中使用 useState​ hook 可以创建一个状态变量和一个更新状态变量的函数。
  • useState​ 接收一个初始状态值,并返回一个数组,其中第一个元素是当前状态值,第二个元素是更新状态值的函数。
  • 调用更新状态值的函数将触发组件的重新渲染
  • useState​ hook 可以被多次使用,以创建多个状态变量和对应的更新函数。

使用函数更新状态值:

setState(prevState => {
  return /* 新状态值 */;
});

参数说明:

  • prevState​:前一个状态值。

示例:

import React, { useState } from 'react';

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

  const handleClick = () => {
    setCount(prevCount => prevCount + 1);
  };

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={handleClick}>Click me</button>
    </div>
  );
}

export default Counter;

详解:

  • 当您需要使用前一个状态值计算新的状态值时,可以使用函数更新状态值的方式。
  • 函数更新状态值将接收前一个状态值作为参数,并返回新的状态值。
  • 函数更新状态值将始终在同步更新之前执行,并且可以避免由于异步更新而引起的竞态条件。

使用惰性初始化:

const [state, setState] = useState(() => {
  return /* 初始状态值 */;
});

参数说明:

  • () => {}​:返回初始状态值的函数。

示例:

import React, { useState } from 'react';

function Counter() {
  const [count, setCount] = useState(() => {
    const initialCount = Number(window.localStorage.getItem('count') || 0);
    return initialCount;
  });

  const handleClick = () => {
    setCount(prevCount => prevCount + 1);
  };

  useEffect(() => {
    window.localStorage.setItem('count', count);
  }, [count]);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={handleClick}>Click me</button>
    </div>
  );
}

export default Counter;

详解:

  • useState​ hook 的参数也可以是一个返回初始状态值的函数,用于惰性初始化状态。
  • 惰性初始化可以延迟计算初始状态值,直到组件首次渲染时执行。
  • 这对于从网络或本地存储中获取数据作为初始状态值非常有用。

使用多个状态变量:

const [state1, setState1] = useState(initialState1);
const [state2, setState2] = useState(initialState2);

示例:

import React, { useState } from 'react';

function UserForm() {
  const [firstName, setFirstName] = useState('');
  const [lastName, setLastName] = useState('');
  const [email, setEmail] = useState('');

  const handleSubmit = event => {
    event.preventDefault();
    console.log(`Name: ${firstName} ${lastName}, Email: ${email}`);
  };

  return (
    <form onSubmit={handleSubmit}>
      <label>
        First name:
        <input type="text" value={firstName} onChange={e => setFirstName(e.target.value)} />
      </label>
      <label>
        Last name:
        <input type="text" value={lastName} onChange={e => setLastName(e.target.value)} />
      </label>
      <label>
        Email:
        <input type="text" value={email} onChange={e => setEmail(e.target.value)} />
      </label>
      <button type="submit">Submit</button>
    </form>
  );
}

export default UserForm;

详解:

  • useState​ hook 可以被多次使用,以创建多个状态变量和对应的更新函数。
  • 对于每个状态变量,必须使用对应的更新函数来更新状态。
  • 使用多个状态变量可以让您在函数组件中保存多个相关数据,而无需使用类组件。

总结:useState​ 是 React Hooks 中最常用的 hook 之一,它允许您在函数组件中使用状态。使用 useState​,您可以创建状态变量和对应的更新函数,并在函数组件中保存数据。您还可以使用函数更新状态值、惰性初始化状态、使用多个状态变量等。

useEffect

useEffect​ 是另一个常用的 hook,它允许您在组件渲染后执行副作用操作。它接受一个回调函数和一个依赖项数组,这些依赖项会影响该回调函数的执行。如果依赖项未发生变化,则该回调函数不会再次执行。

useEffect(() => {
  document.title = `You clicked ${count} times`;
}, [count]);

useEffect​ 是 React Hooks 中常用的 hook 之一,它允许您在组件挂载、卸载或更新时执行副作用操作。以下是 useEffect​ 的全面详解:

useEffect(() => {
  // effect
  return () => {
    // cleanup
  };
}, [dependency]);

参数说明:

  • effect​:副作用操作的函数。
  • cleanup​:清理副作用操作的函数。
  • dependency​:依赖数组,用于控制 effect​ 函数何时重新运行。

返回值:

  • 无。

示例:

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

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

  useEffect(() => {
    document.title = `You clicked ${count} times`;
  }, [count]);

  const handleClick = () => {
    setCount(count + 1);
  };

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={handleClick}>Click me</button>
    </div>
  );
}

export default Counter;

详解:

  • useEffect​ hook 允许您在组件挂载、卸载或更新时执行副作用操作。 useEffect 钩
  • useEffect​ 接收一个函数作为副作用操作,并在组件挂载、卸载或更新时调用该函数。
  • useEffect​ 函数可以返回一个清理函数,在组件卸载或更新时调用该函数。
  • useEffect​ 函数还可以接收一个依赖数组,以控制何时重新运行 effect​ 函数。
  • 如果依赖数组为空,effect​ 函数将仅在组件挂载和卸载时运行。
  • 如果依赖数组不为空,effect​ 函数将在组件挂载和每次依赖项发生更改时运行。

使用 useEffect​ hook 可以处理以下副作用操作:

  • 发起网络请求或访问浏览器 API。
  • 添加或删除 DOM 元素。
  • 订阅或取消订阅事件。
  • 记录日志或统计数据。

使用多个 useEffect​ hook:

useEffect(() => {
  // effect1
  return () => {
    // cleanup1
  };
}, [dependency1]);

useEffect(() => {
  // effect2
  return () => {
    // cleanup2
  };
}, [dependency2]);

示例:

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

function Clock() {
  const [time, setTime] = useState(new Date());

  useEffect(() => {
    const intervalId = setInterval(() => {
      setTime(new Date());
    }, 1000);

    return () => {
      clearInterval(intervalId);
    };
  }, []);

  return <p>The time is {time.toLocaleTimeString()}</p>;
}

export default Clock;

详解:

  • 使用多个 useEffect​ hook 可以为不同的副作用操作定义不同的 effect​ 函数。
  • 每个 useEffect​ hook 都可以定义自己的依赖数组,以控制何时重新运行 effect

useEffect​ hook 的注意事项:

  • useEffect​ 函数在组件首次渲染后异步执行。如果在渲染期间需要同步更新状态,请使用 useLayoutEffect​ hook。
  • 如果 effect​ 函数不需要清理,请忽略返回函数。
  • 如果 effect​ 函数依赖于组件作用域内的变量,必须将这些变量添加到依赖数组中。
  • 如果 effect​ 函数不需要依赖,将空数组作为依赖数组。
  • 如果 effect​ 函数需要访问 props​ 或 state​,必须在依赖数组中添加 props​ 或 state​,以便在 effect​ 函数中访问最新值。
  • 如果 effect​ 函数需要更新 state​,请使用函数形式的 setState​,以避免由于异步更新而引起的竞态条件。

总结:useEffect​ 是 React Hooks 中常用的 hook 之一,它允许您在组件挂载、卸载或更新时执行副作用操作。使用 useEffect​,您可以定义副作用操作和清理操作,并控制何时重新运行 effect​ 函数。您还可以使用多个 useEffect​ hook 和依赖数组来处理不同的副作用操作和依赖项。在使用 useEffect​ 时,请注意异步执行、依赖项和状态更新等问题。

useContext

useContext​ 是一个用于访问 React 上下文的 hook。它接受一个上下文对象,并返回上下文对象中的值。

const value = useContext(MyContext);

useContext​ 是 React Hooks 中常用的 hook 之一,它允许您在组件中使用全局的状态。以下是 useContext​ 的全面详解:

基本用法:

const value = useContext(context);

参数说明:

  • context​:React context 对象。

返回值:

  • value​:React context 的当前值。

示例:

import React, { useState, useContext } from 'react';

const ThemeContext = React.createContext('light');

function Toolbar() {
  const theme = useContext(ThemeContext);

  return (
    <div>
      <button style={{ background: theme }}>Click me</button>
    </div>
  );
}

function App() {
  const [theme, setTheme] = useState('light');

  const toggleTheme = () => {
    setTheme(theme === 'light' ? 'dark' : 'light');
  };

  return (
    <ThemeContext.Provider value={theme}>
      <Toolbar />
      <button onClick={toggleTheme}>Toggle theme</button>
    </ThemeContext.Provider>
  );
}

export default App;

useReducer

useReducer​ 是一个替代 useState 的 hook,它接受一个 reducer 函数和初始状态值,并返回当前状态和一个 dispatch 函数,用于触发状态更新。与 useState 不同,您可以使用 useReducer 来处理更复杂的状态逻辑。

const [state, dispatch] = useReducer(reducer, initialState);

详解:

  • useContext​ hook 可以让您在函数组件中使用全局的状态。
  • useContext​ 接收一个 React context 对象,并返回该 context 的当前值。
  • 您必须使用 React.createContext​ 函数创建 context 对象,并使用 Context.Provider​ 组件提供 context 的值。
  • 在组件中使用 useContext​ hook 可以避免将 context 作为 props​ 传递给所有中间组件的麻烦。
  • 您可以在同一个应用程序中使用多个 context 对象。

在类组件中使用 useContext​:

const value = this.context;

示例:

import React, { Component } from 'react';

const ThemeContext = React.createContext('light');

class Toolbar extends Component {
  static contextType = ThemeContext;

  render() {
    const theme = this.context;

    return (
      <div>
        <button style={{ background: theme }}>Click me</button>
      </div>
    );
  }
}

class App extends Component {
  state = { theme: 'light' };

  toggleTheme = () => {
    this.setState(state => ({ theme: state.theme === 'light' ? 'dark' : 'light' }));
  };

  render() {
    return (
      <ThemeContext.Provider value={this.state.theme}>
        <Toolbar />
        <button onClick={this.toggleTheme}>Toggle theme</button>
      </ThemeContext.Provider>
    );
  }
}

export default App;

详解:

  • 在类组件中使用 useContext​ hook 可以使用 static contextType​ 属性设置 context 对象。
  • contextType​ 属性是一个类属性,它可以设置组件的 this.context​ 属性。
  • 您仍然需要使用 React.createContext​ 函数创建 context 对象,并使用 Context.Provider​ 组件提供 context 的值。

注意事项:

  • 在函数组件中使用 useContext​ hook 时,请确保 context 对象已经存在于应用程序中,并通过 Context.Provider​ 组件提供值。
  • 如果您的组件需要依赖多个 context 对象,请使用多个 useContext​ hook。
  • 如果您使用 useContext​ hook 访问了 context 对象,请确保使用 React.memo​函数来缓存组件,以避免不必要的渲染。

总结:useContext​ 是 React Hooks 中常用的 hook 之一,它允许您在函数组件中使用全局的状态。使用 useContext​,您可以在组件中访问 context 对象的当前值。您需要使用 React.createContext​ 函数创建 context 对象,并使用 Context.Provider​ 组件提供 context 的值。在类组件中,您可以使用 static contextType​ 属性设置 context 对象,或者在 render​ 方法中使用 this.context​ 属性。在使用 useContext​ 时,请注意 context 对象是否存在,并通过 Context.Provider​ 组件提供值。如果您的组件依赖于多个 context 对象,请使用多个 useContext​ hook。

useCallback

useCallback​ 是一个用于缓存回调函数的 hook,它接受一个回调函数和一个依赖项数组,并返回一个 memoized 的回调函数。每当依赖项发生变化时,该 hook 将返回一个新的回调函数。

const memoizedCallback = useCallback(
  () => {
    doSomething(a, b);
  },
  [a, b],
);

useCallback​ 是 React Hooks 中常用的 hook 之一,它可以用于缓存回调函数以避免在每次渲染时创建新的函数。以下是 useCallback​ 的全面详解:

基本用法:

const memoizedCallback = useCallback(
  () => {
    // callback
  },
  [dependency]
);

参数说明:

  • callback​:要缓存的回调函数。
  • dependency​:依赖数组,用于控制何时重新创建回调函数。

返回值:

  • memoizedCallback​:缓存后的回调函数。

示例:

import React, { useState, useCallback } from 'react';

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

  const handleClick = useCallback(() => {
    setCount(count + 1);
  }, [count]);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={handleClick}>Click me</button>
    </div>
  );
}

export default Counter;

详解:

  • useCallback​ hook 可以用于缓存回调函数以避免在每次渲染时创建新的函数。
  • useCallback​ 接收一个回调函数和一个依赖数组,并返回一个缓存后的回调函数。
  • 如果依赖数组不为空,则当依赖项更改时,useCallback​ 将返回一个新的回调函数。
  • 如果依赖数组为空,则 useCallback​ 将始终返回相同的回调函数。
  • 使用 useCallback​ hook 可以提高应用程序的性能,因为它避免了在每次渲染时创建新的回调函数。

在依赖项不变的情况下缓存回调函数:

const memoizedCallback = useCallback(
  () => {
    // callback
  },
  []
);

示例:

import React, { useState, useCallback } from 'react';

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

  const handleClick = useCallback(() => {
    setCount(prevCount => prevCount + 1);
  }, []);

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={handleClick}>Click me</button>
    </div>
  );
}

export default Counter;

详解:

  • 如果依赖数组为空,则 useCallback​ 将始终返回相同的回调函数。
  • 在依赖项不变的情况下缓存回调函数可以提高应用程序的性能,因为它避免了在每次渲染时创建新的回调函数。
  • 如果回调函数依赖于状态或 props​,则必须将这些值添加到依赖数组中。

注意事项:

  • 在使用 useCallback​ hook 时,请确保只缓存必要的回调函数。

  • 如果回调函数没有任何依赖项,则不需要使用 useCallback​ 进行缓存。

  • 如果您在 render​ 方法中使用箭头函数来定义回调函数,则可能需要使用 useCallback

  • 如果回调函数的依赖项在 props​ 中定义,则可能需要将 React.memo​ 函数用于组件。

总结: useCallback​ 是 React Hooks 中常用的 hook 之一,它可以用于缓存回调函数以避免在每次渲染时创建新的函数。使用 useCallback​,您可以定义回调函数并指定其依赖项,以控制何时重新创建函数。在依赖项不变的情况下缓存回调函数可以提高应用程序的性能。在使用 useCallback​ 时,请注意缓存必要的回调函数,并在回调函数依赖于状态或 props​ 时添加依赖项。如果您在 render​ 方法中使用箭头函数来定义回调函数,则可能需要使用 useCallback​ 进行缓存。如果回调函数的依赖项在 props​ 中定义,则可能需要将 React.memo​ 函数用于组件。

useMemo

useMemo​ 是一个用于缓存值的 hook,它接受一个回调函数和一个依赖项数组,并返回一个 memoized 的值。每当依赖项发生变化时,该 hook 将返回一个新的值。

const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

useMemo​ 是 React Hooks 中常用的 hook 之一,它可以用于缓存计算结果以避免在每次渲染时重新计算。以下是 useMemo​ 的全面详解:

基本用法

const memoizedValue = useMemo(
  () => {
    // value
  },
  [dependency]
);

参数说明:

  • value​:要缓存的计算结果。
  • dependency​:依赖数组,用于控制何时重新计算计算结果。

返回值:

  • memoizedValue​:缓存后的计算结果。

示例:

import React, { useState, useMemo } from 'react';

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

  const factorial = useMemo(() => {
    console.log('Calculating factorial...');

    let result = 1;

    for (let i = 1; i <= count; i++) {
      result *= i;
    }

    return result;
  }, [count]);

  return (
    <div>
      <p>{count}! = {factorial}</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

export default Counter;

详解:

  • useMemo​ hook 可以用于缓存计算结果以避免在每次渲染时重新计算。
  • useMemo​ 接收一个计算函数和一个依赖数组,并返回一个缓存后的计算结果。
  • 如果依赖数组不为空,则当依赖项更改时,useMemo​ 将重新计算计算结果。
  • 如果依赖数组为空,则 useMemo​ 将始终返回相同的计算结果。
  • 使用 useMemo​ hook 可以提高应用程序的性能,因为它避免了在每次渲染时重新计算结果。

在依赖项不变的情况下缓存计算结果:

const memoizedValue = useMemo(
  () => {
    // value
  },
  []
);

示例:

import React, { useState, useMemo } from 'react';

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

  const factorial = useMemo(() => {
    console.log('Calculating factorial...');

    let result = 1;

    for (let i = 1; i <= 10; i++) {
      result *= i;
    }

    return result;
  }, []);

  return (
    <div>
      <p>{count}! = {factorial}</p>
      <button onClick={() => setCount(count + 1)}>Click me</button>
    </div>
  );
}

export default Counter;

详解:

  • 如果依赖数组为空,则 useMemo​ 将始终返回相同的计算结果。
  • 在依赖项不变的情况下缓存计算结果可以提高应用程序的性能,因为它避免了在每次渲染时重新计算结果。

注意事项:

  • 在使用 useMemo​ hook 时,请确保只缓存必要的计算结果。

  • 如果计算结果没有任何依赖项,则不需要使用 useMemo​ 进行缓存。

  • 如果计算结果依赖于状态或 props​,则必须将这些值添加到依赖数组中。

  • 如果您的计算函数需要访问全局状态,请考虑使用 useCallback​ 和 useMemo​。

总结:useMemo​ 是 React Hooks 中常用的 hook 之一,它可以用于缓存计算结果以避免在每次渲染时重新计算。使用 useMemo​,您可以定义计算函数并指定其依赖项,以控制何时重新计算结果。在依赖项不变的情况下缓存计算结果可以提高应用程序的性能。在使用 useMemo​ 时,请注意缓存必要的计算结果,并在计算结果依赖于状态或 props​ 时添加依赖项。如果您的计算函数需要访问全局状态,请考虑使用 useCallback​ 和 useMemo​。

useRef

useRef​ 是一个用于创建可变引用的 hook,它可以用于在组件渲染之间存储数据。它返回一个包含当前值的对象,该值在每次渲染时保持不变。

const inputRef = useRef(null);

useEffect(() => {
  inputRef.current.focus();
}, []);

useRef​ 是 React Hooks 中常用的 hook 之一,它可以用于创建一个可变的引用,并在组件渲染时保留该引用。以下是 useRef​ 的全面详解:

基本用法:

const refContainer = useRef(initialValue);

参数说明:

  • initialValue​:初始值。

返回值:

  • refContainer​:一个可变的对象,其中包含 current​ 属性,该属性在组件重新渲染时保持不变。

示例:

import React, { useRef } from 'react';

function TextInput() {
  const inputRef = useRef(null);

  const handleClick = () => {
    inputRef.current.focus();
  };

  return (
    <div>
      <input type="text" ref={inputRef} />
      <button onClick={handleClick}>Focus</button>
    </div>
  );
}

export default TextInput;

详解:

  • useRef​ hook 可以用于创建一个可变的引用,并在组件渲染时保留该引用。
  • useRef​ 接收一个初始值,并返回一个包含 current​ 属性的可变对象。
  • ref​ 属性可以用于引用 DOM​ 元素或组件实例。
  • 使用 useRef​ hook 可以提供对 DOM​ 元素或组件实例的引用,从而允许您访问其属性和方法。
  • ref​ 属性和 useRef​ hook 都允许您在组件之间共享引用。

示例:

import React, { useState, useRef } from 'react';

function Counter() {
  const [count, setCount] = useState(0);
  const prevCountRef = useRef();

  const handleClick = () => {
    prevCountRef.current = count;
    setCount(count + 1);
  };

  const prevCount = prevCountRef.current;

  return (
    <div>
      <p>You clicked {count} times</p>
      {prevCount && (
        <p>
          Previous count: {prevCount}
        </p>
      )}
      <button onClick={handleClick}>Click me</button>
    </div>
  );
}

export default Counter;

详解:

  • useRef​ hook 可以用于在组件之间共享引用。
  • 在此示例中,我们使用 useState​ hook 来跟踪计数,并使用 useRef​ hook 来跟踪以前的计数。
  • 在每次单击按钮时,我们将当前计数存储在 prevCountRef.current​ 中,并将计数增加 1。
  • 然后,我们使用 prevCountRef.current​ 显示以前的计数。

注意事项:

  • 使用 useRef​ hook 可以提供对 DOM​ 元素或组件实例的引用,但请确保只在必要时使用它,因为它可能会破坏 React 的组件模型。

  • 如果您需要在组件之间共享状态,请使用 useContext​ 或 useReducer​。

  • 在使用 useRef​ hook 时,请确保不要将其与 ref​ 属性混淆,因为它们的行为略有不同。

  • ref​ 属性和 useRef​ hook 都允许您在组件之间共享引用,但是 ref​ 属性更适合用于引用 DOM​ 元素,而 useRef​ hook 更适合用于引用组件实例或其他可变值。

总结:useRef​ 是 React Hooks 中常用的 hook 之一,它可以用于创建一个可变的引用,并在组件渲染时保留该引用。使用 useRef​,您可以获得对 DOM​ 元素或组件实例的引用,从而允许您访问其属性和方法。ref​ 属性和 useRef​ hook 都允许您在组件之间共享引用,但是 ref​ 属性更适合用于引用 DOM​ 元素,而 useRef​ hook 更适合用于引用组件实例或其他可变值。在使用 useRef​ hook 时,请确保不要将其与 ref​ 属性混淆,并注意只在必要时使用它,因为它可能会破坏 React 的组件模型。

useImperativeHandle

useImperativeHandle​ 是一个用于暴露自定义方法的 hook,它允许您在父组件中访问子组件的方法。它接受一个 ref 对象和一个回调函数,该回调函数将返回一个 API 对象,该对象将成为 ref 的当前值。

function ChildComponent(props, ref) {
  const inputRef = useRef(null);

  useImperativeHandle(ref, () => ({
    focusInput: () => {
      inputRef.current.focus();
    }
  }));

  return <input type="text" ref={inputRef} />;
}

ChildComponent = forwardRef(ChildComponent);

useLayoutEffect

useLayoutEffect​ 与 useEffect 类似,它也允许您执行副作用操作。但是,它会在浏览器绘制之前同步执行回调函数,以便可以立即更新 DOM。

useLayoutEffect(() => {
  // update DOM synchronously
}, [dependency]);

useDebugValue

useDebugValue​ 是一个用于调试自定义 Hooks 的 hook。它接受一个格式化函数和一个值,并在 React 开发者工具中显示格式化后的值。

function useCustomHook() {
  const [value, setValue] = useState('');

  useDebugValue(value, value => `Value: ${value}`);

  return [value, setValue];
}

以上是 React Hooks 的全部详解,您可以根据需要选择适合您的 hook 来优化您的 React 组件。