React面试题及详细答案150道(51-60)

前后端面试题》专栏集合了前后端各个知识模块的面试题,包括html,javascript,css,vue,react,java,Openlayers,leaflet,cesium,mapboxGL,threejs,nodejs,mangoDB,MySQL,Linux... 。

前后端面试题-专栏总目录

文章目录

  • 一、本文面试题目录
      • [51. 如何在React中实现无限滚动(Infinite Scroll)?](#51. 如何在React中实现无限滚动(Infinite Scroll)?)
      • [52. React中的useCallback和useMemo有什么区别?](#52. React中的useCallback和useMemo有什么区别?)
      • [53. 什么是React的Context API?如何避免Context导致的性能问题?](#53. 什么是React的Context API?如何避免Context导致的性能问题?)
      • [54. 如何在React中实现组件的条件渲染?](#54. 如何在React中实现组件的条件渲染?)
      • [55. 如何在React中实现状态持久化?](#55. 如何在React中实现状态持久化?)
      • [56. 如何在React中实现状态管理?除了Redux还有哪些方案?](#56. 如何在React中实现状态管理?除了Redux还有哪些方案?)
      • [57. 什么是React的StrictMode?它有什么作用?](#57. 什么是React的StrictMode?它有什么作用?)
      • [58. 如何在React中优化大型列表渲染性能?](#58. 如何在React中优化大型列表渲染性能?)
      • [59. 如何在React中实现暗黑模式(Dark Mode)?](#59. 如何在React中实现暗黑模式(Dark Mode)?)
      • [60. 如何在React中实现WebSocket通信?](#60. 如何在React中实现WebSocket通信?)

一、本文面试题目录

51. 如何在React中实现无限滚动(Infinite Scroll)?

无限滚动实现方案

  1. 基于滚动事件监听

    jsx 复制代码
    const [items, setItems] = useState(initialItems);
    const [page, setPage] = useState(1);
    const [isLoading, setIsLoading] = useState(false);
    
    useEffect(() => {
      const handleScroll = () => {
        if (
          window.innerHeight + document.documentElement.scrollTop >=
          document.documentElement.offsetHeight - 500 &&
          !isLoading
        ) {
          setIsLoading(true);
          fetchMoreData(page + 1).then(newItems => {
            setItems([...items, ...newItems]);
            setPage(page + 1);
            setIsLoading(false);
          });
        }
      };
    
      window.addEventListener('scroll', handleScroll);
      return () => window.removeEventListener('scroll', handleScroll);
    }, [items, page, isLoading]);
    
    return (
      <div>
        {items.map(item => <Item key={item.id} {...item} />)}
        {isLoading && <div>Loading...</div>}
      </div>
    );
  2. 使用Intersection Observer API

    jsx 复制代码
    const [items, setItems] = useState(initialItems);
    const [isLoading, setIsLoading] = useState(false);
    const observer = useRef(null);
    
    const loadMoreRef = useCallback(node => {
      if (isLoading) return;
      if (observer.current) observer.current.disconnect();
      
      observer.current = new IntersectionObserver(entries => {
        if (entries[0].isIntersecting) {
          setIsLoading(true);
          fetchMoreData().then(newItems => {
            setItems([...items, ...newItems]);
            setIsLoading(false);
          });
        }
      });
    
      if (node) observer.current.observe(node);
    }, [isLoading, items]);
    
    return (
      <div>
        {items.map(item => <Item key={item.id} {...item} />)}
        <div ref={loadMoreRef}>{isLoading ? 'Loading...' : 'Load more'}</div>
      </div>
    );

52. React中的useCallback和useMemo有什么区别?

核心区别

  • useCallback:缓存函数引用,避免组件重新渲染时创建新函数
  • useMemo:缓存计算结果,避免重复计算

使用场景

  • useCallback

    jsx 复制代码
    const memoizedCallback = useCallback(
      () => doSomething(a, b),
      [a, b]
    );
  • useMemo

    jsx 复制代码
    const memoizedValue = useMemo(() => computeExpensiveValue(a, b), [a, b]);

53. 什么是React的Context API?如何避免Context导致的性能问题?

Context API 用于跨层级传递数据,避免props drilling。

性能优化

  1. 拆分Context

    jsx 复制代码
    // 分离高频变化和低频变化的context
    const UserContext = React.createContext();
    const ThemeContext = React.createContext();
    
    <UserContext.Provider value={user}>
      <ThemeContext.Provider value={theme}>
        <App />
      </ThemeContext.Provider>
    </UserContext.Provider>
  2. 使用useMemo缓存Provider值

    jsx 复制代码
    const themeValue = useMemo(() => ({ theme, setTheme }), [theme]);
    <ThemeContext.Provider value={themeValue}>
      {children}
    </ThemeContext.Provider>
  3. 避免在Provider中使用内联对象

    jsx 复制代码
    // 不好的写法
    <MyContext.Provider value={{ count, setCount }}>
    
    // 优化:使用useMemo缓存对象
    const contextValue = useMemo(() => ({ count, setCount }), [count]);
    <MyContext.Provider value={contextValue}>

54. 如何在React中实现组件的条件渲染?

条件渲染方式

  1. if-else语句

    jsx 复制代码
    function Greeting(props) {
      if (props.isLoggedIn) {
        return <h1>Welcome back!</h1>;
      }
      return <h1>Please sign in.</h1>;
    }
  2. 三元运算符

    jsx 复制代码
    return (
      <div>
        {isLoading ? (
          <Spinner />
        ) : (
          <Content />
        )}
      </div>
    );
  3. 逻辑与运算符(&&)

    jsx 复制代码
    return (
      <div>
        {unreadMessages.length > 0 && (
          <h2>You have {unreadMessages.length} unread messages.</h2>
        )}
      </div>
    );
  4. 状态变量控制

    jsx 复制代码
    const [showComponent, setShowComponent] = useState(false);
    
    return (
      <div>
        <button onClick={() => setShowComponent(!showComponent)}>
          Toggle Component
        </button>
        {showComponent && <MyComponent />}
      </div>
    );

55. 如何在React中实现状态持久化?

状态持久化实现

  1. localStorage + useEffect

    jsx 复制代码
    const [count, setCount] = useState(() => {
      const saved = localStorage.getItem('count');
      return saved ? JSON.parse(saved) : 0;
    });
    
    useEffect(() => {
      localStorage.setItem('count', JSON.stringify(count));
    }, [count]);
  2. 自定义Hook封装

    jsx 复制代码
    function useLocalStorage(key, initialValue) {
      const [value, setValue] = useState(() => {
        const saved = localStorage.getItem(key);
        return saved ? JSON.parse(saved) : initialValue;
      });
    
      useEffect(() => {
        localStorage.setItem(key, JSON.stringify(value));
      }, [key, value]);
    
      return [value, setValue];
    }
    
    // 使用
    const [count, setCount] = useLocalStorage('count', 0);

56. 如何在React中实现状态管理?除了Redux还有哪些方案?

状态管理方案

  1. React内置方案

    • useState/useReducer(局部状态)
    • Context API(全局状态)
  2. 第三方库

    • Redux(复杂应用,单向数据流)
    • MobX(响应式状态管理,基于装饰器)
    • Zustand(轻量级,函数式API)
    • Recoil(Facebook开发,原子化状态)
    • Jotai(极简,原子化状态)
  3. 示例(使用Zustand)

    jsx 复制代码
    import create from 'zustand';
    
    const useCounterStore = create((set) => ({
      count: 0,
      increment: () => set((state) => ({ count: state.count + 1 })),
      decrement: () => set((state) => ({ count: state.count - 1 })),
    }));
    
    // 使用store
    function Counter() {
      const count = useCounterStore((state) => state.count);
      const increment = useCounterStore((state) => state.increment);
      return (
        <div>
          <p>Count: {count}</p>
          <button onClick={increment}>+1</button>
        </div>
      );
    }

57. 什么是React的StrictMode?它有什么作用?

StrictMode 是一个用于检测潜在问题的开发工具,仅在开发环境生效:

检测内容

  1. 不推荐的API使用

    • 废弃的生命周期方法(如componentWillReceiveProps
    • 不安全的findDOMNode使用
    • 过时的context API
  2. 副作用验证

    • 检查useEffect是否正确清除副作用
    • 检测意外的副作用(通过两次调用函数组件)
  3. 安全检查

    • 确保状态初始化纯净
    • 验证getDerivedStateFromProps的使用

启用方式

jsx 复制代码
<React.StrictMode>
  <App />
</React.StrictMode>

58. 如何在React中优化大型列表渲染性能?

列表性能优化

  1. 虚拟列表(Virtualization)

    jsx 复制代码
    import { FixedSizeList } from'react-window';
    
    const Row = ({ index, style }) => {
      return (
        <div style={style}>
          Row {index}: {data[index]}
        </div>
      );
    };
    
    const List = () => (
      <FixedSizeList
        height={600}
        width={800}
        itemSize={35}
        itemCount={data.length}
      >
        {Row}
      </FixedSizeList>
    );
  2. 使用memo防止不必要的重渲染

    jsx 复制代码
    const MemoizedItem = memo(({ item }) => (
      <div>{item.name}</div>
    ));
    
    // 列表渲染
    {items.map((item) => (
      <MemoizedItem key={item.id} item={item} />
    ))}

59. 如何在React中实现暗黑模式(Dark Mode)?

暗黑模式实现

  1. CSS变量 + Context API

    jsx 复制代码
    // ThemeContext.js
    export const ThemeContext = React.createContext();
    
    const ThemeProvider = ({ children }) => {
      const [theme, setTheme] = useState('light');
      const toggleTheme = () => setTheme(theme === 'light' ? 'dark' : 'light');
    
      return (
        <ThemeContext.Provider value={{ theme, toggleTheme }}>
          {children}
        </ThemeContext.Provider>
      );
    };
    
    // 全局样式
    :root {
      --bg-color: #ffffff;
      --text-color: #000000;
    }
    
    .dark-mode {
      --bg-color: #1a1a1a;
      --text-color: #ffffff;
    }
    
    // 使用
    <div className={theme === 'dark' ? 'dark-mode' : ''}>
      <p style={{ color: 'var(--text-color)' }}>Hello World</p>
    </div>

60. 如何在React中实现WebSocket通信?

WebSocket实现

  1. 使用useState和useEffect

    jsx 复制代码
    const [messages, setMessages] = useState([]);
    const [socket, setSocket] = useState(null);
    
    useEffect(() => {
      const ws = new WebSocket('ws://localhost:8080');
      setSocket(ws);
    
      ws.onmessage = (event) => {
        setMessages((prev) => [...prev, JSON.parse(event.data)]);
      };
    
      return () => {
        ws.close();
      };
    }, []);
    
    const sendMessage = (message) => {
      socket?.send(JSON.stringify(message));
    };
  2. 自定义Hook封装WebSocket逻辑

    jsx 复制代码
    function useWebSocket(url) {
      const [messages, setMessages] = useState([]);
      const socketRef = useRef(null);
    
      useEffect(() => {
        socketRef.current = new WebSocket(url);
    
        socketRef.current.onmessage = (event) => {
          setMessages((prev) => [...prev, JSON.parse(event.data)]);
        };
    
        return () => {
          socketRef.current.close();
        };
      }, [url]);
    
      const sendMessage = (message) => {
        socketRef.current.send(JSON.stringify(message));
      };
    
      return { messages, sendMessage };
    }
    
    // 使用
    function Chat() {
      const { messages, sendMessage } = useWebSocket('ws://localhost:8080');
      return (
        <div>
          {messages.map((msg) => (
            <div key={msg.id}>{msg.text}</div>
          ))}
          <button onClick={() => sendMessage({ text: 'Hello' })}>Send</button>
        </div>
      );
    }
相关推荐
weibkreuz15 小时前
React的基本使用@2
前端·javascript·react.js
Hao_Harrision15 小时前
50天50个小项目 (React19 + Tailwindcss V4) ✨ | DragNDrop(拖拽占用组件)
前端·react.js·typescript·tailwindcss·vite7
小鱼小鱼干16 小时前
【Gemini简直无敌了】掌间星河:通过MediaPipe实现手势控制粒子
react.js·gemini
San30.16 小时前
深度驱动:React Hooks 核心之 `useState` 与 `useEffect` 实战详解
前端·javascript·react.js
huohuopro16 小时前
LangChain | LangGraph V1教程 #3 从路由器到ReAct架构
前端·react.js·langchain
打小就很皮...17 小时前
React 实现富文本(使用篇&Next.js)
前端·react.js·富文本·next.js
开发者小天18 小时前
react的拖拽组件库dnd-kit
前端·react.js·前端框架
全栈前端老曹19 小时前
【ReactNative】核心组件与 JSX 语法
前端·javascript·react native·react.js·跨平台·jsx·移动端开发
xiaoxue..20 小时前
React 之 Hooks
前端·javascript·react.js·面试·前端框架
风止何安啊21 小时前
🚀别再卷 Redux 了!Zustand 才是 React 状态管理的躺平神器
前端·react.js·面试