# React

# 属性

  • className

替代class关键字

function App() {
  return <div className="code"></div>;
}
  • style

采用驼峰写法的对象形式

function App() {
  return <div style={{ color: "red" }}></div>;
}
  • htmlFor

替代for关键字

function App() {
  return (
    <div>
      <label forHeml="input">a </label>
      <input id="input" />
    </div>
  );
}

# 生命周期

# 1.组件存在的过程为一个生命周期

mount->update->unmount

# 2. Effect 存在一个生命周期

创建执行->销毁 组件里的 Effect 的挂载和销毁可能会有多次

function App() {
  const [name] = useState("");

  useEffect(() => {
    console.log("create");
    // 当数据name变化时,Effect总会先销毁,后创建
    return () => {
      console.log("unmount");
    };
  }, [name]);
}

# 内置 hook

只能在组件或者其他hooks中使用,不能放在for/if内。

useState

页面中需要驱动的数据,不可改变,只能传入新的值,每次更新都会执行组件函数,如果数据不用在jsx/tsx中,则不需要使用useState来管理,可以用useRef

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

  const onClick = () => {
    setCount(count + 1);
    // setCount((count) => count + 1); // 2
    // setCount((count) => count + 1); 如果是函数,count会取最新的值,重复调用会累加
    // console.log(count) count并不会立即更新
  };
  return <button onClick={onClick}> {count}</button>;
}

useEffect

useEffect 一般用在组件挂载之后执行一些操作(数据获取,更新 dom),里面的函数是在 render 之后,页面更新完后执行, 第二个参数可以限定 Effect 执行时机,如果是空数组,只会在第一次渲染的时候执行,如果传递内容,则会在内容变化的时候执行,会进行销毁后重新挂载

ps: react18在开发环境严格模式下会执行两次(创建->销毁->创建),更早暴露问题。

useEffect(() => {
  const timer = setInterval(() => {
    console.log(1);
  }, 1000);

  // return后面的函数会在组件销毁的时候执行,严格模式在开发的时候会重复执行,所以一般需要return来清理对应的事件或定时等
  return () => {
    clearInterval(timer);
  };
}, []);

useCallback

避免每次 render 重新定义函数

function App() {
  const [count,setCount] = useStae(0)
  // 会保存这个函数的引用
  const handleCb = useCallback(() => {
    console.log("cb");
    // count会缓存,不会因为外部的变化,一直是0
    console.log(count);
  }, []);

  return <div @click={handleCb}> click me </div>
}

useMemo

类似useEffect缓存数据,一般用于数据比较大的情况

useRef

操作dom或者操作普通变量(无法触发 dom 更新)

function App() {
  const inputRef = useRef<HTMLInputElement>(null);
  function handle() {
    const inputEl = inputRef.current;
    if (inputEl) {
      inputEl.select();
    }
  }

  const data = useRef("hello"); // 不会更新,不需要设置

  return (
    <>
      <input ref={inputRef} />
      <button onClick={handle}>{data.current}</button>
    </>
  );
}

useDebugValue 使用在自定义 hook 中,进行输出调试

function useMyhook() {
  useDebugValue("hello");
}

# 自定义 hook

整合通用的逻辑作为一个 hook,达到代码复用的效果

use-immer

基于immer,简化状态管理中不可变数据的更新

import { useImmer } from "use-immer";

function UserData() {
  const [people, setPeople] = useImmer([{ id: 1, name: "alex" }]);

  function add(user) {
    setPeople((draft) => {
      draft.push({
        id: 3,
        name: "bob",
      });
    });
  }

  return <button onClick={() => add({ id: 2, name: "john" })}>add</button>;
}