React学习(进阶)
React 高级主题
以下内容属于 React 的高级主题,适合在掌握了基础知识(如组件、JSX、Props、State、事件处理等)之后深入学习。
1. Context API
Context API 用于在组件树中共享数据,避免通过 Props 层层传递。
代码示例
// 1. 创建一个 Context
const ThemeContext = React.createContext('light');
// 2. 创建一个提供者组件
function App() {
return (
<ThemeContext.Provider value="dark">
<Toolbar />
</ThemeContext.Provider>
);
}
// 3. 中间组件不需要传递任何数据
function Toolbar() {
return (
<div>
<ThemedButton />
</div>
);
}
// 4. 消费 Context 的组件
function ThemedButton() {
const theme = React.useContext(ThemeContext);
return <button style={{ background: theme === 'dark' ? '#333' : '#fff' }}>Themed Button</button>;
}
代码解析:
React.createContext('light')
:创建一个 Context,默认值为'light'
。<ThemeContext.Provider value="dark">
:用Provider
提供数据,value
属性是共享的数据。React.useContext(ThemeContext)
:使用useContext
钩子获取 Context 的值。
2. Refs 和 DOM 操作
Refs 用于直接访问 DOM 元素或组件实例。
代码示例
function TextInputWithFocusButton() {
const inputRef = React.useRef(null);
const handleClick = () => {
inputRef.current.focus();
};
return (
<div>
<input ref={inputRef} type="text" />
<button onClick={handleClick}>Focus the input</button>
</div>
);
}
代码解析:
React.useRef(null)
:创建一个 ref,初始值为null
。ref={inputRef}
:将 ref 绑定到input
元素。inputRef.current.focus()
:通过current
属性访问 DOM 元素并调用focus
方法。
3. 高阶组件(HOC)
高阶组件(HOC) 是一个函数,接收一个组件并返回一个新的组件,用于复用组件逻辑。
代码示例
// 1. 定义一个高阶组件
function withLogger(WrappedComponent) {
return function(props) {
React.useEffect(() => {
console.log(`Component ${WrappedComponent.name} is rendered`);
}, []);
return <WrappedComponent {...props} />;
};
}
// 2. 普通组件
function MyComponent({ message }) {
return <div>{message}</div>;
}
// 3. 使用高阶组件
const LoggedComponent = withLogger(MyComponent);
// 4. 渲染高阶组件
ReactDOM.render(<LoggedComponent message="Hello, HOC!" />, document.getElementById('root'));
代码解析:
withLogger(WrappedComponent)
:一个高阶组件,接收一个组件并返回一个新组件。useEffect
:在新组件中监听挂载事件,打印日志。<WrappedComponent {...props} />
:将原始组件及其 props 渲染出来。
4. Render Props
Render Props 是一种通过 Props 传递渲染逻辑的技术。
代码示例
// 1. 定义一个带有 Render Props 的组件
function MouseTracker({ render }) {
const [position, setPosition] = React.useState({ x: 0, y: 0 });
const handleMouseMove = (event) => {
setPosition({ x: event.clientX, y: event.clientY });
};
return (
<div style={{ height: '100vh' }} onMouseMove={handleMouseMove}>
{render(position)}
</div>
);
}
// 2. 使用 Render Props
function App() {
return (
<MouseTracker render={({ x, y }) => (
<h1>The mouse position is ({x}, {y})</h1>
)} />
);
}
代码解析:
render
Prop:MouseTracker
组件通过render
Prop 接收渲染逻辑。render(position)
:调用render
函数并传递position
数据。({ x, y }) => <h1>...</h1>
:在App
组件中定义渲染逻辑。
5. 性能优化
React 提供了一些方法来优化性能,避免不必要的渲染。
代码示例
// 1. React.memo 优化函数组件
const MemoizedComponent = React.memo(function MyComponent({ message }) {
return <div>{message}</div>;
});
// 2. useCallback 缓存回调函数
function ParentComponent() {
const [count, setCount] = React.useState(0);
const handleClick = React.useCallback(() => {
setCount(prev => prev + 1);
}, []);
return (
<div>
<button onClick={handleClick}>Increment</button>
<MemoizedComponent message={`Count: ${count}`} />
</div>
);
}
代码解析:
React.memo
:缓存函数组件,避免在不必要的 props 变化时重新渲染。React.useCallback
:缓存回调函数,避免在每次渲染时创建新的函数。
6. React 中的错误边界
错误边界 用于捕获子组件的 JavaScript 错误,并显示备用 UI。
代码示例
class ErrorBoundary extends React.Component {
constructor(props) {
super(props);
this.state = { hasError: false };
}
static getDerivedStateFromError(error) {
return { hasError: true };
}
componentDidCatch(error, errorInfo) {
console.error('Caught an error:', error, errorInfo);
}
render() {
if (this.state.hasError) {
return <h1>Something went wrong.</h1>;
}
return this.props.children;
}
}
function App() {
return (
<ErrorBoundary>
<MyComponent />
</ErrorBoundary>
);
}
代码解析:
getDerivedStateFromError
:捕获错误并更新state
。componentDidCatch
:记录错误信息。this.props.children
:渲染子组件或备用 UI。