1.父子组件之间状态传递
最基本的父子组件间状态传递方式是通过 Props
传递
ParentComponent.tsx
import React from 'react';
import ChildComponent from './ChildComponent';
const ParentComponent = () => {
const [count, setCount] = React.useState<number>(0);
return (
<div>
<ChildComponent count={count} onIncrement={() => setCount(c => c + 1)} />
</div>
);
};
ChildComponent.tsx
import React from 'react';
interface ChildProps {
count: number;
onIncrement: () => void;
}
const ChildComponent: React.FC<ChildProps> = ({ count, onIncrement }) => {
return (
<div>
<p>Count: {count}</p>
<button onClick={onIncrement}>Increment</button>
</div>
);
};
2.兄弟组件之间状态传递
通过状态提升将共享状态提升到最近的共同父组件中:
ChildA.tsx
type ChildAProps = {
setSharedState: (value: string) => void;
};
const ChildA = ({ setSharedState }: ChildAProps) => {
return (
<input
type="text"
onChange={(e) => setSharedState(e.target.value)}
/>
);
};
export default ChildA;
ChildB.tsx
type ChildBProps = {
sharedState: string;
};
const ChildB = ({ sharedState }: ChildBProps) => {
return <div>Received: {sharedState}</div>;
};
export default ChildB;
ParentComponent.tsx
import { useState } from 'react';
import ChildA from './ChildA';
import ChildB from './ChildB';
const ParentComponent = () => {
const [sharedState, setSharedState] = useState<string>('');
return (
<div>
<ChildA setSharedState={setSharedState} />
<ChildB sharedState={sharedState} />
</div>
);
};
export default ParentComponent;
3.从上到下的组件状态传递
使用 Context API
进行跨多层组件传递状态
首先,我们创建一个 context 文件,定义类型和 provider:
// contexts/ThemeContext.tsx
import React, { createContext, useContext, useState, ReactNode } from 'react';
// 定义 context 的类型
type Theme = 'light' | 'dark';
interface ThemeContextType {
theme: Theme;
toggleTheme: () => void;
}
// 创建 context 并设置默认值
const ThemeContext = createContext<ThemeContextType | undefined>(undefined);
// 创建 provider 组件
export const ThemeProvider = ({ children }: { children: ReactNode }) => {
const [theme, setTheme] = useState<Theme>('light');
const toggleTheme = () => {
setTheme(prevTheme => (prevTheme === 'light' ? 'dark' : 'light'));
};
return (
<ThemeContext.Provider value={{ theme, toggleTheme }}>
{children}
</ThemeContext.Provider>
);
};
// 创建自定义 hook 以便在组件中使用 context
export const useTheme = () => {
const context = useContext(ThemeContext);
if (context === undefined) {
throw new Error('useTheme must be used within a ThemeProvider');
}
return context;
};
在应用顶层使用 Provider
// App.tsx
import { ThemeProvider } from './contexts/ThemeContext';
import ThemeToggler from './components/ThemeToggler';
import Content from './components/Content';
function App() {
return (
<ThemeProvider>
<div className="app">
<ThemeToggler />
<Content />
</div>
</ThemeProvider>
);
}
export default App;
创建使用 context
的组件
// components/ThemeToggler.tsx
import { useTheme } from '../contexts/ThemeContext';
const ThemeToggler = () => {
const { theme, toggleTheme } = useTheme();
return (
<button onClick={toggleTheme}>
Toggle Theme (Current: {theme})
</button>
);
};
export default ThemeToggler;
使用创建的组件
// components/Content.tsx
import { useTheme } from '../contexts/ThemeContext';
const Content = () => {
const { theme } = useTheme();
return (
<div style={{
padding: '20px',
backgroundColor: theme === 'light' ? '#fff' : '#333',
color: theme === 'light' ? '#000' : '#fff'
}}>
<h1>Current Theme: {theme}</h1>
<p>This content changes based on the selected theme.</p>
</div>
);
};
export default Content;
项目结构
src/
├── contexts/
│ └── ThemeContext.tsx
├── components/
│ ├── ThemeToggler.tsx
│ └── Content.tsx
├── App.tsx
└── main.tsx