1. 首页
  2. React

Vite6+React18+Ts项目-15.几种状态传递方法

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

TOP