useImperativeHandle()
import React, { forwardRef, memo, useImperativeHandle, useRef } from "react";
const HelloZM = memo(
forwardRef((props, ref) => {
const zmInputRef = useRef();
// 子组件对父组件传入的ref进行处理
useImperativeHandle(ref, () => {
return {
//相当于返回给父组件的current对象
focus() {
zmInputRef.current.focus();
},
setValue(value) {
zmInputRef.current.value = value;
},
};
});
return <input type="text" ref={zmInputRef} />;
})
);
const App = memo(() => {
const titleRef = useRef();
const inputRef = useRef();
function handleDOM() {
console.log(inputRef.current); //子组件通过useImperativeHandle暴露出来的对象 {focus: ƒ, setValue: ƒ}
// 在父组件中操作子组件
inputRef.current.focus();
inputRef.current.setValue("hello ww");
}
return (
<div>
<h2 ref={titleRef}>useImperativeHandle App Page</h2>
<HelloZM ref={inputRef} />
<button onClick={handleDOM}>DOM操作</button>
</div>
);
});
export default App;
useLayoutEffect()
执行时机:1 2 3
import React, { memo, useEffect, useLayoutEffect, useState } from "react";
const App = memo(() => {
const [count, setCount] = useState(0);
useLayoutEffect(() => {
console.log("2useLayoutEffect");
});
useEffect(() => {
console.log("3useEffect");
});
console.log("1App render");
return (
<div>
<h2>useLayoutEffect App Page count:{count}</h2>
<button onClick={(e) => setCount(count + 1)}>+1</button>
</div>
);
});
export default App;
计数器闪烁现象:
import React, { memo, useEffect, useState } from "react";
const ChangeNum = memo(() => {
const [count, setCount] = useState(100);
useEffect(() => {
//在dom渲染之后执行,会出现闪烁,0 => 90
console.log("useEffect");
if (count === 0) {
setCount(Math.random() + 90);
}
}, [count]);
console.log("ChangeNum page render");
return (
<div>
<h2>ChangeNum count:{count}</h2>
<button onClick={(e) => setCount(0)}>set 0</button>
</div>
);
});
export default ChangeNum;
import React, { memo, useLayoutEffect, useState } from "react";
const ChangeNum2 = memo(() => {
const [count, setCount] = useState(100);
useLayoutEffect(() => {
//在dom渲染之后执行,会出现闪烁,0 => 90
console.log("useEffect");
if (count === 0) {
setCount(Math.random() + 90);
}
}, [count]);
console.log("ChangeNum page render");
return (
<div>
<h2>ChangeNum count:{count}</h2>
<button onClick={(e) => setCount(0)}>set 0</button>
</div>
);
});
export default ChangeNum2;
自定义Hooks
- 打印生命周期
import React, { memo, useEffect, useState } from "react";
function useLogLife(cName) {
useEffect(() => {
console.log(cName + "组件被创建");
return () => {
console.log(cName + "组件被销毁");
};
}, []);
}
const Home = memo(() => {
useLogLife("home");
return <h1>Home Page</h1>;
});
const About = memo(() => {
useLogLife("about");
return <h1>About Page</h1>;
});
const App = memo(() => {
const [isShow, setIsShow] = useState(true);
useLogLife("app");
return (
<div>
<h2>自定义 App hooks</h2>
<div>
{isShow && <Home />}
{isShow && <About />}
</div>
<button onClick={(e) => setIsShow(!isShow)}> isShow?</button>
</div>
);
});
export default App;
- context获取数据
import { createContext } from "react";
const UserContext = createContext();
const TokenContext = createContext();
export { UserContext, TokenContext };
import { TokenContext, UserContext } from "./pages-learn-hooks/自定义hooks/context";
const root = ReactDOM.createRoot(document.getElementById("root"));
root.render(
<UserContext.Provider value={{ name: "wzm", age: 21 }}>
<TokenContext.Provider value={"zm_token"}>
<App />
</TokenContext.Provider>
</UserContext.Provider>
);
import { useContext } from "react";
import { TokenContext, UserContext } from "../context";
function useUserToken() {
const user = useContext(UserContext);
const token = useContext(TokenContext);
return [user, token];
}
export default useUserToken;
在组件中使用token
import React, { memo, useState } from "react";
import { useUserToken } from "./hooks";
const Home = memo(() => {
const [user, token] = useUserToken();
return (
<h1>
Home Page:{user.name}-{user.age}-{token}
</h1>
);
});
const About = memo(() => {
const [user, token] = useUserToken();
return (
<h1>
About Page:{user.name}-{user.age}-{token}
</h1>
);
});
const App = memo(() => {
const [isShow, setIsShow] = useState(true);
return (
<div>
<h2>自定义 App hooks</h2>
<div>
{isShow && <Home />}
{isShow && <About />}
</div>
<button onClick={(e) => setIsShow(!isShow)}> isShow?</button>
</div>
);
});
export default App;
监听窗口滚动位置
import { useEffect, useState } from "react";
function useScrollPosition() {
const [scrollX, setScrollX] = useState(0);
const [scrollY, setScrollY] = useState(0);
useEffect(() => {
function handleScroll() {
setScrollX(window.scrollX);
setScrollY(window.scrollY);
}
window.addEventListener("scroll", handleScroll);
return () => {
window.removeEventListener("scroll", handleScroll);
};
}, []);
return [scrollX, scrollY];
}
export default useScrollPosition;
import React, { memo, useState } from "react";
import { useScrollPosition } from "./hooks";
import "./style.css";
const Home = memo(() => {
const [scrollX, scrollY] = useScrollPosition();
return (
<h1>
Home Page:{scrollX}-{scrollY}
</h1>
);
});
const About = memo(() => {
const [scrollX, scrollY] = useScrollPosition();
return (
<h1>
About Page:{scrollX}-{scrollY}
</h1>
);
});
const App = memo(() => {
const [isShow, setIsShow] = useState(true);
return (
<div>
<h2>自定义 App hooks</h2>
<div className="app">
{isShow && <Home />}
{isShow && <About />}
</div>
<button onClick={(e) => setIsShow(!isShow)}> isShow?</button>
</div>
);
});
export default App;
localStorage
import React, { memo } from "react";
import useLocalStorage from "./hooks/useLocalStorage";
const App = memo(() => {
//通过key,直接从localStorage中获取一个数据
// const [token, setToken] = useState(localStorage.getItem("token"));
// useEffect(() => {
// localStorage.setItem("token", token);
// }, [token]);
const [token, setToken] = useLocalStorage("token");
function setTokenHandle() {
setToken("zm_token_useLocalStorage");
}
// const [avatarUrl, setAvatarUrl] = useState(localStorage.getItem("avatarUrl"));
// useEffect(() => {
// localStorage.setItem("avatarUrl", avatarUrl);
// }, [avatarUrl]);
const [avatarUrl, setAvatarUrl] = useLocalStorage("avatarUrl");
function setAvatarUrlHandle() {
setAvatarUrl("http://www.zm.com/useLocalStorage/a.jgp");
}
return (
<div>
<h2>自定义 App hooks Page</h2>
<button onClick={setTokenHandle}>setToken({token})</button>
<button onClick={setAvatarUrlHandle}>setAvatar({avatarUrl})</button>
</div>
);
});
export default App;
import { useEffect, useState } from "react";
function useLocalStorage(key) {
// const [data, setData] = useState(JSON.parse(localStorage.getItem(key)));
//useState()可以传递一个函数,立即执行
// 1.从localStorage中获取数据,并且数据创建组件的state
const [data, setData] = useState(() => {
const item = localStorage.getItem(key);
if (!item) return "";
return JSON.parse(item);
});
// 2.监听data改变,一旦发生改变就存储data最新值
useEffect(() => {
localStorage.setItem(key, JSON.stringify(data));
}, [data]);
// 3.将data/setData的操作返回给组件,让组件可以使用和修改值
return [data, setData];
}
export default useLocalStorage;