React
名詞
web component : Web Components is a suite of different technologies allowing you to create reusable custom elements
JSX : 是一個 JavaScript 的語法擴充, 允許我們在 JS 的檔案中使用 HTML 的標籤
Virtual DOM :
Reconciliation : 找出哪些樹節點哪些需要變化
Immutability : 不可變性
Mutation : 修改
JSON Web Token (JWT) : 用來在 身份提供者 和 服務提供者 間傳遞被 認證 的用戶身份訊息,以便於從資源伺服器獲取資源
常用 list
- useState : react 使用的 state, 更動後就會 re-render
- useEffect : 可控制 render 後要做什麼
- useLayoutEffect : 可控制 render 前要做什麼
- useRef : 近似於 useState,但更動後不會 re-render
- memo : 把 component 包起來, 雖然 parents rerender 但本身未改變就不 rerender
- useMemo : 把 data 記起來,未改變就不產生新的
- useCallback : 把 function 記起來,未改變就不產生新的
- useContext : 資料跨多層傳送
- react router : 處理網頁的 route
- useParams : 取得網頁的資訊
- useHistory : 控制網頁跳頁
- styled components : 方便輸入 css
- ThemeProvider : set for theme
- Link : 近似於 a tag
- useLocation : 取得 path name
- Fragment : 一個 component 讓你一次 render 多個 element 而不需要額外的 wrapper
- useReducer : 可執行 dispatch
todolist simulate
1 |
|
基礎
注意事項
- Component 的字首須為大寫字母 : 小寫字母開頭的組件視為原始 DOM 標籤
install and start
1 | # install |
Strict Mode and measuring performance
1 | import { StrictMode } from "react"; |
export and export default
一個js只有一個回傳值,用export default, 有多個回傳值就用export
1 | // ./src/redux/reducers/index.js |
1 | // ./src/redux/actionTypes.js |
1 | // ./src/redux/actions.js |
1st React - include Inline styling
1 | // index.js |
1 | // App.js |
1 | /* App.css */ |
styled components
install
1 | npm install styled-components |
Example 1
- styled-compoents 代替 function
- 可以包下一層, set hover
1 | // App.js |
Example 2
- & + & (相連之 component)
- 傳入props
- TodoItem 移出成為一個 component
1 | // App.js |
Example 3
- media query
1
2
3${MEDIA_QUERY_MD} {
font-size: 16px;
} - re-styled
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16import TodoItem from './TodoItem'
// 對原本存在 function,再做 re-styled
const BlackTodoItem = styled(TodoItem)`
background: black;
`
function App() {
return (
<div className="App">
<TodoItem content="123"/>
<TodoItem content="456" size="XL"/>
<BlackTodoItem content="456" size="XL"/>
</div>
);
} - theme : 使用 ThemeProvider 內層可用 props 取用
- TodoItem component 另存一個 file
index.js
1 | // index.js |
App.js
1 | // App.js |
./constants/style.js
1 | /* ./constants/style.js */ |
TodoItem.js
1 | // TodoItem.js |
Example 4 - 對原本存在 function,再做 re-styled
1 | import React from 'react' |
JSX to react by Babel example
- JSX Prevents Injection Attacks
- dangerouslySetInnerHTML
- tag a run javascript: add encode URI
1
2
3{/* javascript:alert(1) */}
{/* <a href={todo.content}>click me</a> */}
<a href={window.encodeURIComponent(todo.content)}>click me</a>
1 | <button size="XL">hello!</button> |
1 | <button size="XL" onClick={()=> {alert(1)} }>hello!</button> |
1 | <button size="XL" onClick={()=>{alert(1)} }><div>hello!</div></button> |
State
example 1
- state init : const [counter, setCounter] = React.useState(0);
- state ange : setCounter(counter + 1)
- ui upadte : counter: {counter}
1 | // App.js |
example 2 - 多欄位
1 | import React, { useState } from "react"; |
example 3 - todos
- key
- setTodos for array
- todos.map
1 | // App.js |
example 4 - todos add item
- controlled component
- uncontrolled component #1
- uncontrolled component #2 (Ref)
- todo change to object
App.js
1 | // App.js |
TodoItem.js
1 | // TodoItem.js |
example 5 - todos delete
- todo delete
App.js
1 | // App.js |
TodoItem.js
1 | // TodoItem.js |
example 6 - todos change state
- todo change state
App.js
1 | // App.js |
TodoItem.js
1 | // TodoItem.js |
useEffect
- render 後,你想做什麼
exampl 1 - add useEffect
1 | // add useEffect-1 |
exampl 2 - run useEffect when todos change
1 | // save to localStorage after update-1+ |
exampl 3 - run useEffect 1st render
1 | // App.js |
exampl 4 - set local storage to init todos
1 | // App.js |
exampl 5 - clear up LayoutEffects
1 | // App.js |
改寫成自己的 hook
App.js
1 | // App.js |
useInput.js
1 | // useInput.js |
useTodos.js
1 | // useTodos.js |
memo, useMemo, useCallback
- memo - 把 component 包起來, 雖然 parents rerender 但本身未改變就不 rerender
1
2
3// add memo - 傳入不變,即不 re-render
// 但每次 render 會 new handleTodosClick
const MemoButton = memo(Button); - useMemo - 把 data 記起來,未改變就不產生新的
1
2
3
4
5
6// add useMemo - for data
// todos change no run
const s = useMemo(() =>{
console.log('calculate s')
return value ? redStyle : blueStyle;
}, [value]) - useCallback - 把 function 記起來,未改變就不產生新的
1
2
3
4
5
6
7
8
9
10
11
12
13
14
// add useCallback - [] 表沒東西會造成改變
const handleTodosClick = useCallback(() =>{
console.log(value);
// set input value
setTodos([{
id: id.current,
content: value,
isDone: false
}, ...todos])
setValue('')
// use ref
id.current++
}, [setValue, value, todos]);
1 | // App.js |
1 | // useTodos.js |
lazy initializer - useState() 加 function 僅第一次執行
1 | // App.js |
useLayoutEffect
- render 前你想做什麼
exampl 1
1 | // App.js |
class component
example 1
1 | // App.js |
1 | // TodoItem.js |
example 2 - class component lifeCycle 生命週期
- PureComponent : same as memo(props 有變動才update)
- shouldComponentUpdate : return false not update
- componentDidMount : mount
- componentDidUpdate : update
- componentWillUnmount : before unmount(not render the component)
1 | // index.js |
1 | // Counter.js |
useContext
prop Drilling : 資料跨多層傳送
1 | // index.js |
1 | // Demo.js |
useContext example 1
./App.js
1
2
3
4
5
6
7
8
9
10
11// ./App.js
import React from "react";
import ContentExample from "./ContentExample";
export default function App() {
return (
<div>
<ContentExample />
</div>
);
}./ContentExample
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31// ./ContentExample
import React, { createContext, useContext } from "react";
const slogan = "super star";
const Content = createContext();
function SideBarButton(props) {
// get context
const title = useContext(Content);
return <div>{title}</div>;
}
function SideBar(props) {
// get context
const bt = useContext(Content);
return (
<div>
<button>{bt}</button>
<SideBarButton />
</div>
);
}
export default function ContentExample(props) {
return (
// set Context
<Content.Provider value={slogan}>
<SideBar />
</Content.Provider>
);
}useContext example 2
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15// add useContext(also import createContext )
import { useState, useContext, createContext } from "react";
const ColorContext = createContext()
function DemoInnerBoxContent() {
// 取出 colors
const colors = useContext(ColorContext)
}
return (
// colors 透過 createContext 傳送
<ColorContext.Provider value={colors} >
......
</ColorContext.Provider>
)useContext for array
useContext 可動態改變
useContext 中間層可改變
1 | // index.js |
1 | // Demo.js |
propTypes 驗證 props
1 | # 雖然 create-react-app 已安裝, 建議要安裝(因為 React 隨時都有可能更新內部 dependency 的版號,甚至移除 node module) |
add file ./.eslintrc.json
1 | { |
1 | // App.js |
1 | // TodoItem.js |
1 | // useTodos.js |
deployment
local
1 | # build |
deploy to github
add scripts and homepage
package.json
1 | "scripts": { |
insatll gh-pages
1 | npm install --save gh-pages |
github add repository - react-comments-test2
deploy to github
1 | # git init and commit |
open by browser
https://hot5656.github.io/react-comments-test2/
react router
install
1 | npm install react-router-dom |
useParams
1 | // ./Pages/BlogPost/BlogPost.js |
useHistory, useLocation
1 | import { Link, useLocation, useHistory } from "react-router-dom"; |
example #1
./component/App
1 | // ./component/App/App.js |
1 | // ./component/App/index.js |
./component/Header
1 | // ./component/Header/Header.js |
1 | // ./component/Header/index.js |
./Pages/HomePage
1 | // ./Pages/HomePage/HomePage.js |
1 | // ./Pages/HomePage/index.js |
./Pages/LoginPage
1 | // ./Pages/LoginPage/LoginPage.js |
1 | // ./Pages/LoginPage/index.js |
react event
- onClick
- onChange
- onBlur : 離開表單
prettier ESLint
create-react-app default include ESLint configuration
.\node_modules\react-scripts\config\webpack.config.js
1 | !disableESLintPlugin && |
vscode ESlint configuration - ESLint
./.eslintrc.json
1 | { |
prettier - Prettier - Code formatter (Prettier)
settings.json
1 | { |
1 | # 雙引號 |
測試
react-testing-library : 測試 React component
Cypress : end ot end test
Developer Tools
- React Developer Tool
- Storybook
- Bundle Analyzer
- Why Did You Render
- React Testing Library With Jest
- Formik and Yup
- React Hook Form
- React Sight
- React Proto
參考資料
- styled components
- tagged template
- Babel is a JavaScript compiler
- Prettier
- React Setting Up Your Editor
- Introducing JSX
- dangerouslySetInnerHTML
- hook-flow
- A Complete Guide to useEffect
- useLocalStorage
- 從頭打造一個簡單的 Virtual DOM
- 為了瞭解原理,那就來實作一個簡易 Virtual DOM 吧!
- React lifeCycle 生命週期
- react deployment
- react router
- JWT
- react-testing-library
- cypress
- 從零開始學 ReactJS(ReactJS 101)
- Overreacted(Dan Abramov)
- ReactDOMServer : SSR reffence
- PRERENDER io : SSR reference
- *** Next.js : The React Framework for Production (內建 SSR)
- TypeScript: .ts, JavaScript 加型態, 需編譯後才能執行
- React Interview Questions & Answers