何謂 React Hook
Hook 是 React 16.8 中增加的新功能。它讓你不必寫 class 就能使用 state 以及其他 React 的功能。 (from 官方文件)
並「函式」來複用邏輯的概念,重新設計元件,更新粒度更細,讓程式碼更清晰, 並逐步將 class component 替換成函式型元件 Function Component。
何副作用 Effect
呼叫同個方法,給同樣的參數,永遠應該返回同樣的值,react 元件中,給相同的 props ,渲染的 ui應該永遠一樣,但副作用和純函數相反,還處理了和返回值無關的事。
useEffect 異步存取資料
const [count, setCount] = useState(0);
useEffect(() => {
document.title = `點擊${count}`;
}, [count]);
P.S. useEffect 若不帶第二個參數,每次被渲染就會被調用,會造成無窮無死循環,若不想發生可以給他空 array。
P.S. useEffect watch 空 array 時,他只會初始化一次,在 Next JS 時可以當來用戶端初始化事件。
因為 useEffect 是同步方法,但可以用直接 promise,如果要用 async wait,則必在 useEffect 裡擴充一個 async 方法,並執行他
// promise 用法
const responses = fetch(
"https://jsonplaceholder.typicode.com/users"
)
.then(response => response.json())
.then(data => setRobotGallery(data))
或
// async await 用法
useEffect(() => {
const fetchData = async () => {
const res = await fetch("https://jsonplaceholder.typicode.com/users");
const data = await res.json();
setRobotGallery(data);
};
fetchData();
}, []);
Loading
const [loading, setLoading] = useState<boolean>(false);
{!loading ? (
<div className={styles.robotList}>
{robotGallery.map((r) => (
<Robot key={r.id} id={r.id} email={r.email} name={r.name} />
))}
</div>
) : (
<h2>loading</h2>
)}
錯誤處理
const [error, setError] = useState<string>();
try {
throw new Error("網站錯誤")
} catch (e) {
if (e instanceof Error) {
setError(e.message);
}
}
{(!error || error !== "") && <div>{error}</div>}
上下級元件參數傳遞
一般來說可以透過 props 傳遞參數到子元件,但自身不需要这个prop,但为了使子组件能获取到这个prop,則會衍生 Prop Drilling 的問題。
<component test="" />
add perpery props interface
React.FC<props>
P.S. Prop Drilling 簡而言之是指:當一個元件自身不需要這個prop,但為了使子元件能獲取到這個prop,而不得已去傳遞這個prop的行為。
這時就可以用 React 上下文關係 context
const defaultContextValue = {
username: "阿來克斯",
};
export const appContext = React.createContext(defaultContextValue);
const root = ReactDOM.createRoot(
document.getElementById("root") as HTMLElement
);
root.render(
<React.StrictMode>
<appContext.Provider value={defaultContextValue}>
<App />
</appContext.Provider>
</React.StrictMode>
);
使用的元件
import { appContext } from "../index";
<appContext.Consumer>
{(value) => {
return (
<div className={styles.cardContainer}>
<p>{value.username}</p>
</div>
);
}}
</appContext.Consumer>
useContext Hook 簡化寫法,可以不用層層套崁
onst Robot: React.FC<RobotProps> = ({ id, name, email }) => {
const value = useContext(appContext)
return (
<div className={styles.cardContainer}>
<img alt="robot" src={`https://robohash.org/${id}`} />
<h2>{name}</h2>
<p>{email}</p>
<p>{value.username}</p>
</div>
);
};
P.S. 那麼如果,組件若不是上下級關係時,又不想一層層傳進去,則需要考慮用 redux 這種狀態管理的機制進行管理