React 学习笔记,从入门到精通,持续记录

相关书籍:https://www.zhihu.com/pub/book/119565131

React Native:https://github.com/reactnativecn/react-native-guide

Create React App:https://create-react-app.dev/ 

Jsx和虚拟Dom

最简易的 React 示例如下:

const root = ReactDOM.createRoot(document.getElementById('root'));
root.render(<h1>Hello, world!</h1>);

1.什么是jsx?

Jsx的出现是为了更加方便的创建虚拟dom,它是一个 JavaScript 的语法扩展,JSX 可以很好地描述 UI 应该呈现出它应有交互的本质形式。

在 JSX 语法中,可以在大括号内放置任何有效的 JavaScript 表达式。例如,2 + 2,user.firstName 或 formatName(user) 都是有效的 JavaScript 表达式。

const name = 'Josh Perez';
const element = <h1>Hello, {name}</h1>;

相关文档:https://zh-hans.reactjs.org/docs/introducing-jsx.html

2.create-react-app

脚手架:https://github.com/facebook/create-react-app

3.props

当传递给组件的 props 发生变化时,React 会认为组件的输出可能不同,因此会触发组件的重新渲染。

  • 值的变化:如果 props 的值发生变化(例如,父组件传递的 props 值被更新),React 会重新渲染子组件。
  • 引用的变化:即使 props 的值没有改变,但其引用发生了变化(例如,父组件传递了一个新的对象或数组),React 也会认为 props 发生了变化并重新渲染子组件。

hook

1.useEffect

useEffect它的作用主要是用来处理副作用(side effects)。

副作用 是指在组件渲染过程中,除了更新组件的 DOM 外,还需要执行的额外操作。这些操作可能包括与浏览器的交互(如操作 DOM、设置样式、监听事件等)、与外部数据源的交互(如发起网络请求获取数据)、或修改全局状态等。

通过 useEffect 的第二个参数(依赖项数组),可以控制副作用的执行时机。如果依赖项数组为空([]),则表示副作用只在组件首次渲染时执行一次;如果依赖项数组中有值,则表示当这些依赖项的值发生变化时,副作用才会重新执行。

useEffect 返回一个清理函数(cleanup function),用于在组件卸载或副作用重新执行前,清理上一次副作用产生的资源。

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

function MyComponent() {
  useEffect(() => {
    // 副作用逻辑
    console.log('副作用执行了');

    // 返回清理函数
    return () => {
      console.log('清理函数执行了');
    };
  });

  return <div>MyComponent</div>;
}

//当组件卸载时,清理函数会被调用,并打印出 "清理函数执行了"。

2.useState

useState接收一个初始值作为参数,并返回一个状态变量和一个更新该状态的函数。

import React, { useState } from 'react';

function Counter() {
  // 初始化状态为 0
  const [count, setCount] = useState(0);

  return (
    <div>
      <p>{count}</p>
      <button onClick={() => setCount(count + 1)}>Increment</button>
    </div>
  );
}

setCount 是异步的,React 会在下一次渲染时更新状态。这意味着如果你在 setCount 的回调中立即读取新的状态值,可能无法获取到最新的状态。

不要直接修改状态的值,而是通过 setXXX 函数来更新状态。直接修改状态可能会导致 React 无法检测到状态的变化,从而不会触发组件的重新渲染。

3.useMemo

useMemo是一个性能优化的 Hook,用于避免在每次组件渲染时都重复计算某些昂贵的函数调用或复杂逻辑。它可以帮助你提升组件的渲染性能,尤其是在处理性能开销较大的计算时非常有用。

// 使用 useMemo 缓存计算结果
  const computedValue = useMemo(() => {
    // 这里是一个昂贵的计算过程,例如数组的排序、过滤等
    return size * 2;
  }, [size]); // 依赖项数组,只有 size 变化时才会重新计算

4.useCallback

useCallback用于缓存函数引用。当你有一个函数,这个函数的引用在每次组件渲染时都可能发生变化(例如,函数内部依赖于某些状态或 props),useCallback 可以确保函数的引用保持不变,避免不必要的重新渲染。

状态变化会触发组件渲染,组件渲染后会重新生成函数的引用,假如这个函数传到了下级组件,会触发下级组件的无意义更新

5.useRef

useRef的主要作用是创建一个可变的引用对象,这个对象在组件的整个生命周期内保持不变。可以通过它来存储一些需要持久化的值或 DOM 元素的引用。

保存普通的可变变量,但是变化时不需要触发渲染时,必须使用useRef:

  1. 使用普通变量,每次渲染都会重新初始化变量值。
  2. 与useState不同的是,useRef变化不会触发组件更新。

保存DOM:

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

function FocusInput() {
  // 创建一个 ref 对象,用于存储 DOM 元素的引用
  const inputRef = useRef(null);

  // 使用 useEffect 在组件加载完成后执行聚焦操作
  useEffect(() => {
    // inputRef.current 指向 DOM 元素
    if (inputRef.current) {
      inputRef.current.focus(); // 聚焦到文本框
    }
  }, []); // 依赖项数组为空,表示只在组件加载完成后执行一次

  return (
    <div>
      <input ref={inputRef} type="text" placeholder="聚焦的文本框" />
    </div>
  );
}

export default FocusInput;