【理论】React Hooks全解

2022-02-16  本文已影响0人  darkTi
  • Hook 是 React 16.8 的新增特性,所以使用Hook 时要保证React版本在16.8及以上。
  • npm info react versions ,用来获取react所有的版本号;
  • 有了Hook我们就不需要在class里面去声明状态了

useState

useReducer

1、基础用法

import React, { useReducer } from "react";
import ReactDOM from "react-dom";

const initFormValue = {
  name: "",
  age: 18,
  nationality: "汉族"
};

function reducer(state, action) {
  switch (action.type) {
    case "patch":
      return { ...state, ...action.formData };
    case "reset":
      return initFormValue;
    default:
      throw new Error();
  }
}

function App() {
  const [formData, dispatch] = useReducer(reducer, initFormValue);
  const onReset = () => {
    dispatch({ type: "reset" });
  };

  return (
    <div>
      <form onReset={onReset}>
        <div>
          姓名
          <input
            value={formData.name}
            onChange={(e) =>
              dispatch({ type: "patch", formData: { name: e.target.value } })
            }
          />
        </div>
        <div>
          年龄
          <input
            value={formData.age}
            onChange={(e) =>
              dispatch({ type: "patch", formData: { age: e.target.value } })
            }
          />
        </div>
        <div>
          民族
          <input
            value={formData.nationality}
            onChange={(e) =>
              dispatch({
                type: "patch",
                formData: { nationality: e.target.value }
              })
            }
          />
        </div>
        <div>
          <button type="submit">提交</button>
          <button type="reset">重置</button>
        </div>
        <hr />
        {JSON.stringify(formData)}
      </form>
    </div>
  );
}
const rootElement = document.getElementById("root");
ReactDOM.render(<App />, rootElement);

2、用useReducer代替Redux

总的来说,useReducer是useState的复杂版;

useContext

1、上下文

2、使用方法

①先创建上下文,const C = React.createContext(null)
②使用<C.Provider value={}></C.Provider>圈定作用域;
③在作用域内使用useContext(C)来使用上下文;

3、useContext不是响应式的

useEffect

1、副作用

2、用途

useEffect(()=>{}, []),在第一次变化后执行,相当于componentDidMount;
useEffect(()=>{}, [n]),只有在n变化的时候才执行(包含第一次渲染),相当于componentDidUpdate;
useEffect(()=>{}),任何一个变量变化就执行;
useEffect(()=>{.... return () => {}}),通过添加一个return来执行组件要消失时刻的操作,相当于componentWillUnmount;

上面这几种用途可同时存在;
可同时使用多个useEffect,它们之间是不冲突的;且是按照顺序来执行;

useLayoutEffect

import React, { useState, useEffect } from "react";
import ReactDOM from "react-dom";
import "./styles.css";

const App = () => {
  const [value, setValue] = useState(0);
  
 // 这里再换成useLayoutEffect看有什么不同呢
  useEffect(() => {
    document.querySelector("#x").innerText = `value: 1000`;
  }, [value]);

  return (
    <div id="x" onClick={() => setValue(0)}>
      value: {value}
    </div>
  );
};

ReactDOM.render(<App />, document.querySelector("#root"));

1、含义

2、特点

3、总结

useMemo

1、React.Memo()

function App() {
  const [n, setN] = React.useState(0);
  const [m, setM] = React.useState(0);
  const onClick = () => {
    setN(n + 1);
  };

  return (
    <div className="App">
      <div>
        <button onClick={onClick}>update n {n}</button>
      </div>
      <Child data={m} />
    </div>
  );
}

function Child(props) {
  console.log("child 执行了");
  console.log("假设这里有大量代码");
  return <div>child: {props.data}</div>;
}
const Child = React.memo((props) => {
  console.log("child 执行了");
  console.log("假设这里有大量代码");
  return <div>child: {props.data}</div>;
});

2、useMemo()用法

function App() {
  const [n, setN] = React.useState(0);
  const [m, setM] = React.useState(1);
  const onClick = () => {
    setN(n + 1);
  };

  const onClickChild = () => {
    console.log("点击child 了");
  };

  return (
    <div className="App">
      <div>
        <button onClick={onClick}>update n {n}</button>
      </div>
      <Child data={m} onClick={onClickChild} />
    </div>
  );
}

const Child = React.memo((props) => {
  console.log("child 执行了");
  console.log("假设这里有大量代码");
  return <div onClick={props.onClick}>child: {props.data}</div>;
});
 const onClickChild = React.useMemo(() => {
    return () => {
      console.log(m, "点击child 了");
    };
  }, [m]);

3、useMemo()的特点

注意!如果你的value是个函数,你就要这么写,React.useMemo(()=> (x)=> console.log(x)),这是一个返回函数的函数,是不是很难用,所以就有了useCallback~~~

4、useCallback

useRef

1、目的

2、count.current的值变化时不会自动render

forwardRef

1、什么时候用到它呢

useImperativeHandle

useState / useReducer ===> 它们里面的n每次都变;
useMemo / useCallback ===> 当依赖[m]变的时候,返回的值就变化;
useRef ===> 它的值永远不变;

自定义Hook

Stale Closure

总结

image.png
上一篇 下一篇

猜你喜欢

热点阅读