React基础与实践 | 青训营笔记
React简介与特性
React特点
- 声明式
- 组件化
- 跨平台编写
等待资源加载实践和大部分情况下浏览器单线程执行是影响web浏览器性能的主要原因
_ErrorBoundary
class ErrorBoundary extends React.Component {
constructor(props) {
super(props)
this.state = { hasError: false }
}
static getDerivedStateFromError() {
// 更新state 使下一次渲染能够实现降级UI
return { hasError: true }
}
componentDidCatch(error, errorInfo) {
logger.error(error, errorInfo)
}
render() {
if (this.state,hasError) {
return <Empty description='xxx' />
}
return this.props.children
}
}
React 更新流程
-
Scheduler ( 调度器 )
- 维护时间切片
- 与浏览器任务调度
- 优先级调度
-
Reconciler ( 协调器 )
- 将 JSX 转化为 Fiber
- Fiber 树对比 ( 双缓存 )
- 确定本次更新的 Fiber
-
Renderer ( 渲染器 ):渲染器用于管理一棵 React 树, 使其根据底层平台进行不同的调用
React基础温故知新
用React开发web应用
- 架构:打包配置 JSX -> babel -> JS , 加载优化和错误降级
- 路由:React Router 向应用中快速的添加视图和数据流,保持页面与URL间的同步
- UI:可复用 UI -> 组件 -> 页面,可复用逻辑抽离成 hook
- 状态:多页面多组件共享信息 redux & context
Hook使用规则
- 只能在最顶层使用 Hook
// 错误示例代码
if (xxx) {
useEffect() {}
}
// 正确示例代码
useEffect() {
if (xxx)
}
-
只能在React函数中调用Hook
- 在React函数组件中 或 自定义 Hook中调用
- 自定义Hook必须以use开头
- Hook中的state是完全隔离的
父组件给子组件通信
案例1:父组件通过选择size大小传递给子组件表单 进行展示
// SizeWrapper
<div>
{
React.Children.map(children, (child) => {
if (child && child.props) {
return React.cloneElement(child, commonProps)
}
return child
})
}
</div>
// before
<div>
<Input value='input' size={props.size} />
<InputTag value={['input-tag']} size={props.size} />
</div>
// after
<SizeWrapper size={props.size}>
<Input value='input' />
<InputTag value={['input-tag']} />
</SizeWrapper>
案例2:父组件给子组件传递一个对象,实现form表单的改变和清空
const FormComponent = (props, ref) {
const [fromInstance] = Form.useForm()
// 给 ref 添加 change,clear 方法
useImperativeHandle(ref, () => {
change: () => formInstance.setFieldsValue(newValue),
clear: () => formInstance.clearFields(['username', 'email'])
})
return ...
}
// 转发ref
const FormConponentWithRef = forwardRef(FormComponent);
const FromWrapper = () => {
const formRef = useRef(null)
return <div>
<Button onClick={()=>formRef.current?.change()}>change</Button>
<Button onClick={()=>formRef.current?.clear()}>clear</Button>
<FromComponentWithRef ref={formRef} />
</div>
}
案例3:组件间共享信息——context & reducer
// 定义 reducer
export const userReducer = (state, action) => {
switch (action.type) {
case 'SET':
return action.user
case 'UPDATE':
return {...state, ...action.user}
case 'REMOVE':
return undefined
default:
return state
}
}
// 创建公共状态容器 store
export default createStore(userReducer)
// 一、传递context
export const GlobalContext = createContext({})
export default () => {
const [state, dispatch] = useReducer(userReducer, store)
return
<GlobalContext.Provider value={{ state, dispatch }} >
<xxx />
</GlobalContext.Provider>
}
function xxx() {
const { state: user, dispatch } = useContext(GlobalContext)
const login = (user) => dispatch?.({ type: 'SET', user })
}
// 二、传递Store
import store from './store'
import { Provider } from 'react-redux'
export default () => {
<Provider store={store}>
<xxx />
</Provider>
}
function xxx(props) {
const { login, logout, user } = props
return xxx
}
export default connnect(
(state: IUserInfo) => ({ user: state })
(dispatch) => ({
login: (user:IUserInfo) => dispatch({ type:'SET', user })
logout: () => dispatch({ type: 'REMOVE' })
})
)(xxx)