react rooks

hooks注意事项
  1. hooks不能再class组件中使用
  2. 只能在最外层调用hooks,不能再循环,判断,子函数中调用
  3. 只能在react的函数组件中调用hooks
useState

状态值

const [count,setCount] = useState(0);  // 0 初始值
const [person, setPerson] = useState({
  name: 'zs',
  age: 19
})
// 1. state更新第一种方式
setCount(count + 1)// 2. 函数式更新
setCount(() => count + 1);
// 3. 引用类型更新 使用扩展符形式
setCount({...person,name:20})

// 4. 如果数据没有更新,则页面不会发生渲染
useEffect

集合了几个的生命周期,不能放到if中。

useEffect(() => {
  console.log('component did mount'); // componentDidMount
  return () => {
     console.log('component will unmount'); // componentWillUnmount
  }
  return null;
})

useEffect(() => {
  console.log("hello"); // componentWillReceiveProps
},[props.value,props.next]) // 只要有任意一个属性改变,就会执行


useRef
import { useRef, useImperativeHandle, forwardRef } from "react";
// forwardRef 函数式组件不运行将ref作为props进行传递给子组件
const Child = forwardRef((props: {}, ref: any) => {
  const inputRef = useRef<any>();
  // useImperativeHandle:减少 子组件暴露的内容
  useImperativeHandle(ref, () => ({
    focus: () => {
      inputRef.current.focus();
    },
  }));

  return (
    <>
      <input type="text" ref={inputRef} />
    </>
  );
});

export default function Parent() {
  const childRef = useRef<any>();
  const handleClick = () => {
    childRef.current.focus();
  };
  return (
    <div>
      <p>RefComponent</p>
      <button onClick={handleClick}>聚焦</button>
      <Child ref={childRef} />
    </div>
  );
}


useContext

useContext只能声明在函数式组件内部。

// 顶层组件
import { createContext } from "react";
import Middle from "./MiddleComponent";

const theme = {
  light: "#fff",
  dark: "#000",
  background: "pink",
};

export const ThemeContext = createContext(theme);
function Context() {
  return (
    <ThemeContext.Provider value={theme}>
      <Middle />
    </ThemeContext.Provider>
  );
}

export default Context;


// 中间组件

import Bottom from "./Bottom";

function Middle() {
  return <Bottom />;
}

export default Middle;

// 底层组件
import { useContext } from "react";
import { ThemeContext } from ".";

function Bottom() {
  const theme = useContext(ThemeContext);

  return <div style={{ backgroundColor: theme.background }}>2232323</div>;
}

export default Bottom;
useLayoutEffect

与useEffect函数效果一样,不过useLayoutEffect是在更新后立即执行,而useEffect中间可能穿插许多其他的事情,所以一般是在useEffect出错的情况下再使用useLayoutEffect。

useReducer

父子组件的通信: 利用useReducer,useContext可以进行父子组件间的通信(useReducer可以操作父组件的内容,useContext可以获取父组件间的内容)

import { useReducer } from 'react';
// 第一个参数: reducer:处理更新的reducer,
// 第二个参数:initialArg: 状态初始值
// 第三个参数:init: 状态初始化函数  将第二个参数,作为init函数的参数,将返回的结果作为state的初始值
const [state,dispatch] = useReducer(reducer,initialArg,init);



// 父组件
import { useReducer } from "react";
import BottomReducer from "./BottomReducer";

function reducer(
  state: { count: number },
  action: { type: string; payload?: number }
) {
  switch (action.type) {
    case "increment":
      return add(state, action.payload);
    case "decrement":
      return { count: state.count - 1 };
    case "reset":
      return init(action.payload as number);
    default:
      throw new Error();
  }
}

interface reducerProp {
  initialCount: number;
}

function init(initialCount: number) {
  return { count: initialCount };
}

function add(state: { count: number }, payload = 1) {
  return { count: state.count + payload };
}

export default function ReducerComponent({ initialCount }: reducerProp) {
  const [state, dispatch] = useReducer(reducer, initialCount, init);
  return (
    <div>
      <p>{state.count}</p>
      <button
        onClick={() => {
          dispatch({ type: "reset", payload: initialCount });
        }}
      >
        reset
      </button>
      <button
        onClick={() => {
          dispatch({ type: "increment" });
        }}
      >
        +
      </button>
      <button
        onClick={() => {
          dispatch({ type: "decrement" });
        }}
      >
        -
      </button>

      <BottomReducer dispatch={dispatch} state={state} />
    </div>
  );
}

// 子组件
export default function BottomReducer({
  dispatch,
  state,
}: {
  dispatch: React.Dispatch<{
    type: string;
    payload?: number | undefined;
  }>;
  state: { count: number };
}) {
  const double = () => {
    dispatch({ type: "increment", payload: 2 });
  };
  return (
    <div>
      <p>BottomReducer</p>
      <p>{state.count}</p>
      <button onClick={double}>+2</button>
    </div>
  );
}
useCallback

当依赖没有发生改变的时候,该函数也不会发生改变,主要用于性能优化(memo+useCallback)

Memo:当父组件传递给子组件的props不发生改变,则子组件不会进行渲染。

函数内部没有返回值

import { useState, useCallback, memo } from "react";
function Counter() {
  const [count, setCount] = useState(0);

  const handleClick = () => {
    setCount(count + 1);
  };

  const childClick = useCallback(() => {}, []);

  return (
    <div>
      <p>useCallback</p>
      <p>{count}</p>
      <button onClick={handleClick}>click</button>
      <Child click={childClick} />
    </div>
  );
}

const Child = memo(function Child({ click }: { click: () => void }) {
  console.log(click);

  console.log("子组件被触发了");
  return <></>;
});
export default Counter;
useMemo

传入的函数内部需要返回值,和useCallback的主要区别。

useMemo只能生命在函数式组件内部

useMemo不但可以返回值,还能返回dom结构。

import { useState, useMemo } from "react";

function MemoComponent() {
  const [a, setA] = useState(0);
  const [b, setB] = useState(0);
  const [c, setC] = useState(0);

  const handleClick = (type: string) => {
    if (type === "a") {
      setA(a + 1);
    } else if (type === "b") {
      setB(b + 1);
    } else {
      return false;
    }
  };

  const d = useMemo(() => {
    return a + b;
  }, [a, b]);
  return (
    <>
      <p>a:{a}</p>
      <p>b:{b}</p>
      <p>d:{d}</p>

      <button
        onClick={() => {
          handleClick("a");
        }}
      >
        +a
      </button>
      <button
        onClick={() => {
          handleClick("b");
        }}
      >
        +b
      </button>
    </>
  );
}
export default MemoComponent;

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值