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
};
}
}