Skip to content

useRef 和 useContext 等其他 Hooks

其他 Hooks

  • useRef
  • useContext
  • useReducer
  • useMemo
  • useCallback

useRef 使用

例子

js
import React, { useEffect, useRef } from 'react';

function UseRefDemo() {
  const btnRef = useRef(null); // 初始值
  const numRef = useRef(100);
  console.log(numRef.current); // 100

  useEffect(() => {
    console.log(btnRef.current); // DOM 节点 <button>click</button>
  }, []);

  return (
    <div>
      <button ref={btnRef}>click</button>
    </div>
  );
}

export default UseRefDemo;

useContext 使用

例子

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

const themes = {
  light: {
    foreground: '#000',
    background: '#eee',
  },
  dark: {
    foreground: '#fff',
    background: '#222',
  },
};
// 创建 Context
const ThemeContext = React.createContext(themes.light);

// 孙子组件
function ThemeButton() {
  const theme = useContext(ThemeContext);
  return (
    <button style={{ background: theme.background, color: theme.foreground }}>
      hello world
    </button>
  );
}

// 子组件
function Toolbar() {
  return (
    <div>
      <ThemeButton></ThemeButton>
    </div>
  );
}

// 父组件
function UseContextDemo() {
  return (
    <ThemeContext.Provider value={themes.dark}>
      <Toolbar></Toolbar>
    </ThemeContext.Provider>
  );
}

export default UseContextDemo;

useReducer 的使用

useReducer 能代替 redux 吗

  • useReducer 是 useState 的替代方案,用于 state 复杂变化
  • useReducer 是单个组件状态管理,组件通讯还需要 props
  • redux 是全局的状态管理,多组件共享数据

例子

js
import React, { useReducer } from 'react';

const initialState = { count: 0 };
const reducer = (state, action) => {
  switch (action.type) {
    case 'increment':
      return { count: state.count + 1 };
    case 'decrement':
      return { count: state.count - 1 };
    default:
      return state;
  }
};

function UseReducerDemo() {
  // 很像 const [count,setCount] = useState(0)
  const [state, dispatch] = useReducer(reducer, initialState);

  return (
    <div>
      count: {state.count}
      <button onClick={() => dispatch({ type: 'increment' })}>increment</button>
      <button onClick={() => dispatch({ type: 'decrement' })}>decrement</button>
    </div>
  );
}

export default UseReducerDemo;

useMemo 使用

使用 useMemo 做性能优化

  • React 默认会更新所有子组件
  • class 组件使用 SCU 和 PureComponect 做优化
  • Hooks 中使用 useMemo,但优化的原理是相同的

例子

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

// 子组件
// function Child({userInfo}) {
//   console.log('child render ...', userInfo)
//
//   return <div>
//     <p>this is child {userInfo.name} {userInfo.age}</p>
//   </div>
// }

// 类似 class PureComponent,对 props 进行浅层比较
const Child = memo(({ userInfo }) => {
  console.log('child render ...', userInfo);

  return (
    <div>
      <p>
        this is child {userInfo.name} {userInfo.age}
      </p>
    </div>
  );
});

// 父组件
function UseMemoDemo() {
  console.log('parent render ...');

  const [count, setCount] = useState(0);
  const [name, setName] = useState('lzw');

  // const userInfo = {name, age: 20}
  // 用 useMemo 缓存数据,有依赖
  const userInfo = useMemo(() => {
    return { name, age: 21 };
  }, [name]);

  return (
    <div>
      <p>
        count is {count}
        <button onClick={() => setCount(count + 1)}>click</button>
      </p>
      <Child userInfo={userInfo}></Child>
    </div>
  );
}

export default UseMemoDemo;

useCallback 使用

使用 useCallback 做性能优化

  • useMemo 缓存数据
  • useCallback 缓存函数
  • 两者是 React Hooks 的常见优化策略

例子

js
import React, { memo, useMemo, useState, useCallback } from 'react';

// 子组件, memo 类似 class PureComponent,对 props 进行浅层比较
const Child = memo(({ userInfo, onChange }) => {
  console.log('child render ...', userInfo);

  return (
    <div>
      <p>
        this is child {userInfo.name} {userInfo.age}
      </p>
      <input onChange={onChange} />
    </div>
  );
});

// 父组件
function UseCallbackDemo() {
  console.log('parent render ...');

  const [count, setCount] = useState(0);
  const [name, setName] = useState('lzw');

  // 用 useMemo 缓存数据,有依赖
  const userInfo = useMemo(() => {
    return { name, age: 21 };
  }, [name]);

  // function onChange(e) {
  //   console.log(e.target.value)
  // }
  // 用 useCallback 缓存函数
  const onChange = useCallback((e) => {
    console.log(e.target.value);
  }, []);

  return (
    <div>
      <p>
        count is {count}
        <button onClick={() => setCount(count + 1)}>click</button>
      </p>
      <Child userInfo={userInfo} onChange={onChange}></Child>
    </div>
  );
}

export default UseCallbackDemo;

基于 MIT 许可发布