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.jsonpackage-lock.json 依赖包本地目录:npm_modules/

npm常用命令

  • npm install -g <module>: 全局安装
  • npm install --save-dev: 调试安装,不会写到package.json
  • npm uninstall <module>:卸载
  • npm init -y:初始化

参考:npm crash course

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.jsonpackage-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')
)
  1. ReactDOM.render将JSX渲染为真实的的DOM。
  2. rootpublic/index.html中的id

1.10 React Component Definition (Advanced)

定义componenet的几个pattern

  1. functional component 函数的方式定义component
  2. arrow function
  3. 定义一个类,继承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:

    1. state定义在多个子component都需要访问的component中(state和面向对象中类的属性有明显的不同)
    1. 子component通过props和callback来显示和更新state
    1. state和state updater更像是event和event handler
    1. 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区别:

  1. handler似乎更专注ui
  2. 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

imperativedeclarative

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

类似发布事件:

  1. 定义reducer,根据current state,type,action计算下一个状态
  2. 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

onSubmithandler: react中处理表单提交的事件

总结

  1. 熟悉JSX语法
  2. 熟悉javascript的一些语法,例如arrow function, destructuring, promise, async/await
  3. 熟悉几个react hooks的用法

参考

  • 不熟悉前端的必读:https://www.robinwieruch.de/javascript-fundamentals-react-requirements
2021-03-27 14:49:15 +0800 yajw Copy old posts A