React

5 分钟
45 阅读
React

React 的函数组件(Function Component)在引入 Hooks 后,可以实现类组件的所有功能,并且代码更简洁、逻辑更复用。以下是 React 函数组件的高级用法详解:


1. 核心 Hooks 进阶

(1) useState - 状态管理

  • 惰性初始化:避免每次渲染都计算初始值。
    jsx 复制代码
    const [state, setState] = useState(() => {
      const initialValue = computeExpensiveValue(); // 只执行一次
      return initialValue;
    });
  • 函数式更新:依赖前一个状态时使用。
    jsx 复制代码
    setCount(prevCount => prevCount + 1);

(2) useEffect - 副作用管理

  • 依赖项优化
    • 空数组 []:仅在组件挂载/卸载时执行(类似 componentDidMount + componentWillUnmount)。
    • 特定依赖 [dep]:仅在 dep 变化时执行。
    jsx 复制代码
    useEffect(() => {
      const subscription = props.source.subscribe();
      return () => subscription.unsubscribe(); // 清理函数
    }, [props.source]);
  • 异步处理
    jsx 复制代码
    useEffect(() => {
      const fetchData = async () => {
        const result = await axios.get('/api/data');
        setData(result.data);
      };
      fetchData();
    }, []);

(3) useMemo & useCallback - 性能优化

  • useMemo:缓存计算结果,避免重复计算。
    jsx 复制代码
    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);
  • useCallback:缓存函数,避免子组件不必要的重渲染。
    jsx 复制代码
    const handleClick = useCallback(() => {
      console.log('Clicked:', id);
    }, [id]);

2. 自定义 Hooks

封装可复用的逻辑(替代 HOC 或 Render Props)。

示例:自定义 useFetch Hook

jsx 复制代码
function useFetch(url) {
  const [data, setData] = useState(null);
  const [loading, setLoading] = useState(true);

  useEffect(() => {
    const fetchData = async () => {
      const response = await fetch(url);
      const result = await response.json();
      setData(result);
      setLoading(false);
    };
    fetchData();
  }, [url]);

  return { data, loading };
}

// 使用
function MyComponent() {
  const { data, loading } = useFetch('/api/data');
  if (loading) return <div>Loading...</div>;
  return <div>{data}</div>;
}

3. Context + useReducer - 状态管理

替代 Redux 的轻量级方案。

(1) 创建 Context

jsx 复制代码
const MyContext = React.createContext();

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

  return (
    <MyContext.Provider value={{ state, dispatch }}>
      <ChildComponent />
    </MyContext.Provider>
  );
}

(2) 定义 Reducer

jsx 复制代码
function reducer(state, action) {
  switch (action.type) {
    case 'INCREMENT':
      return { count: state.count + 1 };
    case 'DECREMENT':
      return { count: state.count - 1 };
    default:
      return state;
  }
}

(3) 在子组件中使用

jsx 复制代码
function ChildComponent() {
  const { state, dispatch } = useContext(MyContext);
  return (
    <button onClick={() => dispatch({ type: 'INCREMENT' })}>
      Count: {state.count}
    </button>
  );
}

4. Refs 与 DOM 操作

(1) useRef - 获取 DOM 或保存可变值

jsx 复制代码
function TextInput() {
  const inputRef = useRef(null);

  useEffect(() => {
    inputRef.current.focus(); // 自动聚焦
  }, []);

  return <input ref={inputRef} />;
}

(2) forwardRef - 转发 Ref 到子组件

jsx 复制代码
const FancyInput = React.forwardRef((props, ref) => (
  <input ref={ref} className="fancy-input" />
));

function Parent() {
  const inputRef = useRef();
  return <FancyInput ref={inputRef} />;
}

5. 高级模式

(1) 动态导入与代码分割(React.lazy

jsx 复制代码
const LazyComponent = React.lazy(() => import('./LazyComponent'));

function App() {
  return (
    <Suspense fallback={<div>Loading...</div>}>
      <LazyComponent />
    </Suspense>
  );
}

(2) 错误边界(Error Boundaries)

jsx 复制代码
class ErrorBoundary extends React.Component {
  state = { hasError: false };

  static getDerivedStateFromError(error) {
    return { hasError: true };
  }

  render() {
    if (this.state.hasError) {
      return <h1>Something went wrong.</h1>;
    }
    return this.props.children;
  }
}

// 使用
<ErrorBoundary>
  <BuggyComponent />
</ErrorBoundary>

6. 性能优化技巧

  1. React.memo:避免不必要的子组件重渲染。
    jsx 复制代码
    const MemoizedComponent = React.memo(MyComponent);
  2. 虚拟列表(react-window:优化长列表渲染。
    jsx 复制代码
    import { FixedSizeList as List } from 'react-window';
    <List height={600} itemCount={1000} itemSize={35}>
      {({ index, style }) => <div style={style}>Item {index}</div>}
    </List>

总结

功能 实现方式
状态管理 useState, useReducer
副作用 useEffect, useLayoutEffect
性能优化 useMemo, useCallback, React.memo
复用逻辑 自定义 Hooks
跨组件通信 Context + useContext
DOM 操作 useRef, forwardRef

掌握这些高级用法后,可以更高效地开发复杂 React 应用,同时保持代码的可维护性和性能。

评论

评论

发表评论