hooks

199 阅读1分钟

1 渲染次数问题

function Child() {  console.log("Child render");  useEffect(() => {    console.log("Child useEffect");  }, []);  return (    <div>      <p>Comp</p>    </div>  );}

const App = () => {  console.log("App 页面刷新了");  const [count, setCount] = useState(0);  const add = () => {    setCount(count + 1);  };  return (    <div>
      <Child></Child>

       <div>{count}</div>      <button onClick={add}>+1</button>    </div>  );};

首次渲染 打印顺序为

  • App 页面刷新了
  • Child render
  • Child useEffect

点击按钮后打印顺序为

  • App 页面刷新了
  • Child render

如何让子组件不渲染,?加入memo,

但是子组件如果有props如,即使子组件加入memo,依然会重新渲染,此时需要在fn上加入 useCallback 才能阻止子组件渲染

 <Child fn={ val=> console.log(val)}></Child>

2 hook中的经典settimeout问题

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

  const log = () => {
    setCount(count + 1);
    setTimeout(() => {
      console.log(count);
    }, 3000);
  };

  return (
    <div>
      <p>You clicked {count} times</p>
      <button onClick={log}>Click me</button>
    </div>
  );
}

解决办法1: useref(0) 缺点-会改变原始值

解决办法2  useEffect  + useRef + useState

3 hook中的经典setinterval问题

单个变量的情况  用setCount的函数形式

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

  useEffect(() => {
    const id = setInterval(() => {
      setCount(c => c + 1);
    }, 1000);
    return () => clearInterval(id);
  }, []);

  return <h1>{count}</h1>;
}

多个变量的情况用usereducer

function reducer(state, action) {
  switch (action.type) {
    case "increment":
      return {
        ...state,
        count: state.count + 1
      };
    default:
      return state;
  }
}
function Counter() {
  const [state, dispatch] = useReducer(reducer, initialState);
  const { count, step } = state;

  useEffect(() => {
    const id = setInterval(() => {
      dispatch({ type: "tick" });
    }, 1000);
    return () => clearInterval(id);
  }, [dispatch]);

  return <h1>{count}</h1>;
}

function reducer(state, action) {
  switch (action.type) {
    case "tick":
      return {
        ...state,
        count: state.count + state.step
      };
  }
}