工程笔记
文档
本篇目录
文档
- React 官网
- dan 博客
- React 通关秘籍
- 玩转 React Hooks
- Build Your Own React
- React 进阶实践指南
- React 技术揭秘
- 从0实现 React18
- 源码流程图
- 深入浅出 React19
- 我的源码调试 Demo
- 我的 React 学习 Demo
学习源码推荐看一遍 Build Your Own React,了解基本流程,再边调试源码边看源码流程图
手写 Context 主题切换
Theme-context.tsx 通过 createContext 创建一个 Context 对象,传入默认值,同事封装一个 hook 用于获取 Context 对象
import { createContext, useContext } from 'react'
export type Theme = 'light' | 'dark'
type ThemeContextType = {
theme: Theme
setTheme: (theme: Theme) => void
}
export const ThemeContext = createContext<ThemeContextType>({
theme: 'dark',
setTheme: () => {}
})
export const useTheme = () => {
const context = useContext(ThemeContext)
if (context === undefined) {
throw new Error('useTheme must be used within a ThemeProvider')
}
return context
}
Theme-provider.tsx,通过 value 属性提供 Context 对象
import { useState } from 'react'
import { ThemeContext, type Theme } from './theme-context'
export const ThemeProvider = ({ children }: { children: React.ReactElement }) => {
const [theme, setTheme] = useState<Theme>('dark')
const value = {
theme,
setTheme
}
return <ThemeContext.Provider value={value}>{children}</ThemeContext.Provider>
}
Consumer.tsx,Consumer 组件,用于消费 Context 对象, useContext 在前面已经封装好了
import { ThemeContext } from './theme-context'
import { ThemeProvider } from './theme-provider'
import { useContext } from 'react'
const InnerContext = () => {
const { theme, setTheme } = useContext(ThemeContext)
return (
<div className="size-40 bg-gray-200">
<button className="cursor-pointer" onClick={() => setTheme('light')}>
切换主题
</button>
<p>当前主题: {theme}</p>
</div>
)
}
const ContextTheme = () => {
return (
<ThemeProvider>
<InnerContext />
</ThemeProvider>
)
}
export default ContextTheme
React 优化将变的部分与不变部分分离
普通的性能优化有 React.memo 和 useMemo 和 useCallback,React.lazy 等
将变的部分与不变部分分离,这种思路可以减少父组件更新,子组件也更新,减少不必要的渲染
父组件(父组件更新,子组件也更新)
import { useState } from 'react'
import Expensive from './Expensive'
const Index = () => {
const [count, setCount] = useState(0)
return (
<div>
<div>count: {count}</div>
<br />
<button className="cursor-pointer rounded-md bg-blue-500 p-2 text-white" onClick={() => setCount(count + 1)}>
点击加1
</button>
<br />
<br />
<Expensive />
</div>
)
}
export default Index
子组件(耗时组件)
const Expensive = () => {
console.log('Expensive 组件渲染')
const now = performance.now()
while (performance.now() - now < 1000) {
// 模拟耗时操作
}
return (
<div>
<div>Expensive</div>
</div>
)
}
export default Expensive
可以把父组件需要更新的部分,也就是下面这段代码单独抽离成一个组件
<div>count: {count}</div>
<br />
<button
className="bg-blue-500 text-white p-2 rounded-md cursor-pointer"
onClick={() => setCount(count + 1)}
>
点击加1
</button>