Try   HackMD

React Beginner Guide: Learn the Must-Know Concepts with Examples

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

*前情提要:通常在跟陌生人交流前,需要理解的基本React知識,這樣才不會一問三不知。以下會先以:props、state、context、refs 以及 lifecycle去做簡單介紹。


Props (屬性)

從父元件中傳進子元件的資料,是唯讀的,不可在子元件中被更改。

//子元件 function Welcome(props) { return <h1> Hello, {props.neme}!</h1>; } //父元件 function App(){ return <Welcome name="CHRIS" />; }

State (狀態)

元件內部可變的資料,用來控制UI變化。

import { useState } from 'react'; function Counter() { //定義兩個參數 const [count, setCount] = useState(0); return ( <div> <p>You clicked {count} times </p> <button onClick={() => setCount(count +1)}>Click me</button> </div> ) }

Context (上下文)

提供跨元件(不需層層傳 props)共享資料的方式,例如主題、語言、登入狀態等。通常跟props 用途區別為是否許多元件都需要使用到Value,以登入/登出為例:

import { creatContext, useContext, useState} from 'react'; //1.建立 Context const AuthContext = creatContext(); //2.建立Provider物件 export function AuthProvider({children}) { const [isLoggedIn, setIsLoggedIn] = useState(false); const login = () => setIsLoggedIn(true); const logout = () => setIsLoggedIn(false); return ( <AuthContext.Provider value={{ isLoggedIn, login, logout }}> {children} </AuthContext.Provider> ); } // 3. 建立自訂 Hook export function useAuth() { return useContext(AuthContext); }
import { useAuth } from './AuthContext'; function LoginButton() { const { login, isLoggedIn } = useAuth(); if (isLoggedIn) return null; return <button onClick={login}>Log in</button>; } export default LoginButton;
import { useAuth } from './AuthContext'; function LogoutButton() { const { logout, isLoggedIn } = useAuth(); if (!isLoggedIn) return null; return <button onClick={logout}>Log out</button>; } export default LogoutButton;
import { useAuth } from './AuthContext'; function UserStatus() { const { isLoggedIn } = useAuth(); return <p>{isLoggedIn ? 'You are logged in!' : 'You are not logged in.'}</p>; } export default UserStatus;
import { AuthProvider } from './AuthContext'; import LoginButton from './LoginButton'; import LogoutButton from './LogoutButton'; import UserStatus from './UserStatus'; function App() { return ( <AuthProvider> <h1>Welcome to My App</h1> <UserStatus /> <LoginButton /> <LogoutButton /> </AuthProvider> ); } export default App;

可能會好奇為什麼能夠使用AuthContext.Provider的寫法,這攸關於Context底層:

  1. Provider: // 用來「提供」值
  2. Consumer: …, // 用來「接收」值(早期寫法)

createContext() 回傳的物件裡面就有這兩個屬性!可以直接寫 <AuthContext.Provider />

Value: 是共享值,在這邊代表傳給AuthContext的共享值,透過useContext(AuthContext)可以存取Value裡面的值。

Image Not Showing Possible Reasons
  • The image was uploaded to a note which you don't have access to
  • The note which the image was originally uploaded to has been deleted
Learn More →

Refs (參考)

直接取得 DOM 元素或元件實例的參考,常用來處理像是表單聚焦、動畫、播放控制、滾動捲軸到某處、讀取 DOM 的寬高位置、控制畫布(canvas)、SVG 或第三方元件等。

import { useRef } from 'react'; //點按鈕時,input 元素會被自動聚焦 function TextInputWithFocusButton() { const inputRef = useRef(null); const handleClick = () => { inputRef.current.focus(); // 直接操作 DOM }; return ( <> <input ref={inputRef} type="text" /> <button onClick={handleClick}>Focus the input</button> </> ); }

image

Lifecycle (生命週期)

指一個元件從被建立、更新、到被卸載(移除)的整個過程,就像是一個元件「出生 → 活著 → 死亡」的歷程。現階段基本上都是使用Hooks中useEffect去實現;不過也可以透過非Hooks的方式去實現,但只能使用Class Component的方式去實現。

以下透過兩種方式去呈現比較:

  1. 掛載(Mounting): 元件第一次出現在畫面上
  2. 更新(Updating): props 或 state 改變時
  3. 卸載(Unmounting): 元件從畫面移除時

分別對應:

  1. useEffect(() => {…}, [])
  2. useEffect(() => {…}, [依賴])
  3. useEffect 的 return function
  1. Hooks:
import { useEffect } from 'react'; function MyComponent(props) { useEffect(() => { console.log('掛載:componentDidMount'); return () => { console.log('卸載:componentWillUnmount'); }; }, []); // 空依賴陣列,只在掛載/卸載時執行 useEffect(() => { console.log('更新:props 或 state 改變'); return () => { console.log('清理上一次更新 effect'); }; }, [props.something]); // 有依賴才是更新 }
  1. Class Component
class MyComponent extends React.Component { componentDidMount() { // 掛載:元件出現在畫面時執行 console.log('componentDidMount'); } componentDidUpdate(prevProps, prevState) { // 更新:元件 state 或 props 改變時執行 console.log('componentDidUpdate'); } componentWillUnmount() { // 卸載:元件從畫面上移除時執行 console.log('componentWillUnmount'); } render() { return <div>Hello Lifecycle!</div>; } }

場景應用:

image