The road to react 笔记
1. Fundamentals of React
1.1 Hello React
SPA: 相比每次从服务端请求一个完整的html文件,SPA使得一个js和一个html文件就能完成客户端的绝大部分功能。页面的切换通过js就能完成。 React就是一种能够实现SPA应用或者遵循了SPA原则的技术。 Component是React中的一个重要概念,一个Component定义了它的html/css/js即样式和交互,它能够被整个应用中灵活地复用。 作者认为的React的优势:稳定,且拥有强大的生态和社区。
1.2 Requirements
编辑器: VSCode 运行环境:node 包管理:npm
依赖包的定义:package.json
和package-lock.json
依赖包本地目录:npm_modules/
npm常用命令
npm install -g <module>
: 全局安装npm install --save-dev
: 调试安装,不会写到package.json
npm uninstall <module>
:卸载npm init -y
:初始化
1.3 Setting up a React Project
npx命令: execute npm package binaries
create-react-app
: 一个创建/初始化react项目骨架的工具
通过create-react-app
所创建的react项目基本结构:
node_modules/
: 依赖目录public/index.html
: 默认src/
下的js是处理这个文件package.json
和package-lock.json
,同上,另外前者定义了start
/build
/test
命令src/App.js
:应用的Components定义src/App.css
:Components样式src/index.js
:应用入口
1.4 Meet the React Component
import React from 'react';
const target = 'React'
function App() {
return (
<div>
<h1>Hello {target}</h1>
</div>
)
}
export default App;
这个component叫做App,同时也是一个普通的js function,所以也叫做function component。 这个component返回一段类似html的叫做JSX的代码。 这个component就是一个普通的js function,可以定义变量以及任何符合js语法的逻辑。
1.5 React JSX
JSX语法:结合html和js
- 特殊关键字:
htmlfor
,className
,onClick
{}
包含的是js表达式
1.6 Lists in React
js语法中list有map
, filter
等方法,也可以用在JSX中:
const App = () => (
<div>
{items.map(item => (<div key={item.objectID}>{item.title}</div>))}
</div>
)
key
用来标识一个node。
return null
表示不生成任何html。
1.7 Meet another React Component
一个定义好的component,可以作为JSX的标签来使用。
const Item = ({item}) => (
<div key={item.objectID}>{item.title}</div>
)
const App = () => (
<div>
{items.map(item => (<Item item={item}/>))}
</div>
)
一个react应用由此会形成一个组件树。
1.8 React Component instantiation
js中的class:
class Item {
constructor(title) {
this.title = title
}
}
const item1 = new Item('test')
当使用JSX语法定义一个component的标签时,也就创建了一个component的实例。
1.9 React DOM
ReactDOM.render(
<App />,
document.getElementById('root')
)
ReactDOM.render
将JSX渲染为真实的的DOM。root
是public/index.html
中的id
1.10 React Component Definition (Advanced)
定义componenet的几个pattern
- functional component 函数的方式定义component
- arrow function
- 定义一个类,继承
React.Component
1.11 Handler Function in JSX
const App = () => {
const handleChange = event => {
console.log(event.target.value)
}
return (
<div>
<label htmlFor="search">Search: </label>
<input id="search" type="text" onChange={handleChange}>
</div>
)
}
synthetic event
合成事件是对浏览器native event的封装,并且改变了某些行为(例如避免submit时刷新页面)。
JSX中event handler和js的语法十分相似。
1.12 React Props
props可以用来在父component到子component的传递参数。
const App = () => (
<div>
{items.map(item => <Item item={item}>)}
</div>
)
const Item = props => (
<div>
<span>{props.item.title}</span>
</div>
)
1.13 React State
React State能够让component变得interactive。
React.useState()
- 是一个
React Hook
- 返回一个二元素的数组,第一个是
current state
,第二个是state updater function
- 当
state updater
被调用后,component会重新render
const App = () => {
const [searchTerm, setSearchTerm] = React.useState('');
...
}
1.14 Callback Handlers in JSX
props是向下传递的。
怎么才能让子component传递信息给父component呢?
- 父component定义一个callback函数,通过props传递给子component
- 子component在处理事件时,调用这个callback函数,实现通知
1.15 Lifting State in React
lift state up
:
-
- state定义在多个子component都需要访问的component中(state和面向对象中类的属性有明显的不同)
-
- 子component通过props和callback来显示和更新state
-
- state和
state updater
更像是event和event handler
- state和
-
- state的"作用域"是整个app的生命周期,所以更像是事件
1.16 React Controlled Components
controlled component
:把state通过props传递给组件,这时能够拿到state的初始值,同时component变得和普通的html元素几乎一样(除了使用JSX语法表示外)。
component lifecycle
:最开始是组件树初始化,同时hooks也用初始值实例化,然后ui就接受各种交互事件,更新state,调用state updater
,然后所有相关的component重新render
特别注意一点:通过各种方式(函数式)定义的component,并不会重新实例化。而Hook也只实例化一次。react内部会去track所有的state。
1.17 Props Handling (Advanced)
props借助js的descruction语法能够更加简洁。
const Item = ({title}) => (
<div><span>{title}</span></div>
)
js支持嵌套解耦(nested descructuing)
spread operator
: <Item {...item} />
rest operator
: const List = ({list}) => list.map(({objectID, ...item}) => <Item key={objectID} {...item} />);
1.18 React Side-Effects
const [searchTerm, setSearchTerm] = React.useState(
localStorage.getItem('search') || 'React'
)
React.useEffect(() => {
localStorage.setItem('search', searchTerm);
}, [searchTerm])
const handleSearch = event => {
setSearchTerm(event.target.value);
}
类似注册一个state
的"事件"处理器。
和handler区别:
- handler似乎更专注ui
- useEffect更专注处理逻辑(非ui,更接近业务)
1.19 React Custom Hooks (Advanced)
useSemiPersistentState
封装了一些特定的逻辑,构成一个custom hook
const useSemiPersistentState = (key, initialState) => {
const [value, setValue] = React.useState(
localStorage.getItem(key) || initialState
);
React.useEffect(() => {
localStorage.setItem(key, value);
}, [value]); // 此处应该是笔误,书中是传递[value, key]
return [value, setValue];
}
1.20 React Fragments
component返回时如果不想要<div>
包着,需要定义每个元素的key,react支持<>
即所谓fragment,来表示top-level element,但是不会有rendered output。
const Search = ({search, onSearch}) = (
<>
<label ... />
<input ... />
</>
)
1.21 Resuable React Component
从search box抽象出InputWithLabel
,结合js的default parameter
语法,能够让component容易复用。
1.22 React Component Composition
children
prop是react的一个特殊的prop,能够支持react component像html element那样嵌套组合:
const Input = ({id, children}) => (
<>
<input id={id} ... />
</>
)
const App = () => (
<div>
<Input id="search">
<strong>Search:</strong>
</Input>
</div>
)
1.23 Imperative React
imperative
和declarative
react也支持直接访问dom element,来做一些事:
const Input = (isFocused=false) => {
const ref = React.useRef()
React.useEffect(() => {
if (isFocused && ref.current) {
ref.current.focus();
};
}, [isFocused]);
return (
<>
<input ref={ref}/>
</>
)
}
1.24 Inline Handler in JSX
const Item = ({item, onRemoveItem}) => (
<>
<button onClick={() => onRemoveItem(item)}>
</>
)
1.25 React Asynchronous Data
Promise
的使用:.then
, .catch
1.26 React Conditional Rendering
{isLoading ? (<p>Loading...</p>):()}
1.27 React Advanced State
React.useReducer
类似发布事件:
- 定义reducer,根据current state,type,action计算下一个状态
- dispatchFunc: 发布action
1.28 React Impossible States
使用useReducer hook封装多个相关的状态,减少impossible states
发生的概率。impossible state
发生表示bug,或者带来错误的用户体验。
1.29 Data Fetching with React
fetch
api: fetch(url).then(resp => resp.json()).then...
1.30 Data Re-Fetching in React
useEffect绑定一个state,当state变化时会执行对应逻辑,更新或者发布action
1.31 Memorized Handler in React (Advanced)
React.useCallback
: 状态发生变化时,直接调用该callback
死循环?没太看懂
1.32 Explicit Data Fetching with React
使用"按钮按下"的side effect来发api请求,而不是每次input change。
想清楚ui是如何交互的,何时发生什么事件,然后再设计state。
1.33 Third-Party Libraries in React
fetch
是浏览器的api,axios
是一个library,用来发异步的请求。
npm install axios
import axios from 'axios'
axios.get(url).then(...)
1.34 Async/Await in React(Advanced)
async () => {
const result = await axios.get(url) // wait
}
1.35 Forms in React
event.preventDefault()
: prevent browser reload
onSubmit
handler: react中处理表单提交的事件
总结
- 熟悉JSX语法
- 熟悉javascript的一些语法,例如arrow function, destructuring, promise, async/await
- 熟悉几个react hooks的用法
参考
- 不熟悉前端的必读:https://www.robinwieruch.de/javascript-fundamentals-react-requirements