React中父组件向子组件通过props传值的几种写法

182 阅读2分钟

基于TypeScript。

基础 Props 传递

// 子组件
type ChildProps = {
  name: string;
  age: number;
};

const ChildComponent: React.FC<ChildProps> = ({ name, age }) => {
  return <div>{name} is {age} years old</div>;
};

// 父组件
const ParentComponent = () => {
  return <ChildComponent name="Alice" age={25} />;
};

展开运算符传递

// 子组件
type ProfileProps = {
  firstName: string;
  lastName: string;
  email: string;
};

const Profile: React.FC<ProfileProps> = (props) => {
  // ...
};

// 父组件
const ParentComponent = () => {
  const userData = {
    firstName: 'John',
    lastName: 'Doe',
    email: 'john@example.com'
  };
  
  return <Profile {...userData} />;
};

传递子元素

// 子组件
type CardProps = {
  title: string;
  children: React.ReactNode; // 可以是 JSX, 字符串, 数组等
};

const Card: React.FC<CardProps> = ({ title, children }) => {
  return (
    <div className="card">
      <h2>{title}</h2>
      <div className="content">{children}</div>
    </div>
  );
};

// 父组件
const ParentComponent = () => {
  return (
    <Card title="Welcome">
      <p>This is the card content</p>
      <button>Click me</button>
    </Card>
  );
};

传递组件

// 子组件
type LayoutProps = {
  header: React.ReactNode;
  sidebar: React.ReactNode;
  content: React.ReactNode;
};

const Layout: React.FC<LayoutProps> = ({ header, sidebar, content }) => {
  return (
    <div className="layout">
      <div className="header">{header}</div>
      <div className="sidebar">{sidebar}</div>
      <div className="content">{content}</div>
    </div>
  );
};

// 父组件
const ParentComponent = () => {
  return (
    <Layout
      header={<h1>App Title</h1>}
      sidebar={<nav>Menu items...</nav>}
      content={<main>Main content...</main>}
    />
  );
};

传递函数

// 子组件
type ButtonProps = {
  onClick: (event: React.MouseEvent) => void;
  label: string;
};

const Button: React.FC<ButtonProps> = ({ onClick, label }) => {
  return <button onClick={onClick}>{label}</button>;
};

// 父组件
const ParentComponent = () => {
  const handleClick = (event: React.MouseEvent) => {
    console.log('Button clicked', event);
  };
  
  return <Button onClick={handleClick} label="Click me" />;
};

使用 Context API 跨层级传递

// 创建 Context
type ThemeContextType = {
  theme: 'light' | 'dark';
  toggleTheme: () => void;
};

const ThemeContext = React.createContext<ThemeContextType | undefined>(undefined);

// 父组件 (Provider)
const ParentComponent = () => {
  const [theme, setTheme] = useState<'light' | 'dark'>('light');
  
  const toggleTheme = () => {
    setTheme(prev => prev === 'light' ? 'dark' : 'light');
  };
  
  return (
    <ThemeContext.Provider value={{ theme, toggleTheme }}>
      <ChildComponent />
    </ThemeContext.Provider>
  );
};

// 子组件 (Consumer)
const ChildComponent = () => {
  const context = useContext(ThemeContext);
  
  if (!context) {
    throw new Error('ChildComponent must be used within a ThemeProvider');
  }
  
  const { theme, toggleTheme } = context;
  
  return (
    <button onClick={toggleTheme}>
      Current theme: {theme}
    </button>
  );
};

context API 简介

Context API 是 React 提供的一种组件间数据共享机制,它允许你在组件树中跨层级传递数据,而无需手动通过 props 逐层传递。Context 主要用于解决"prop drilling"(属性钻取)问题。

基本概念

  • Provider:提供数据的组件
  • Consumer:消费数据的组件
  • Context 对象:创建共享数据的容器

基本用法

  1. 创建Context
import React from 'react';

// 创建Context并设置默认值
const MyContext = React.createContext(defaultValue);
  1. 提供数据(Provider)
<MyContext.Provider value={/* 共享的值 */}>
  {/* 子组件 */}
</MyContext.Provider>
  1. 消费数据
import { useContext } from 'react';

function ChildComponent() {
  const contextValue = useContext(MyContext);
  // 使用contextValue
}

Context API使用场景

  1. 主题切换
  2. 用户登录状态、认证信息共享
  3. 全局状态管理
  4. 表单管理:复杂表单额状态共享,特别是表单校验和多步骤表单

最佳实践

  1. 合理拆分Context:不要将所有全局状态放在一个Context中,按功能拆分
  2. 性能优化:使用React.memo避免不必要的重渲染
  3. 类型安全:在TypeScript中为Context提供完整类型定义
  4. 提供默认值:为Context设置合理的默认值
  5. 自定义Hook:为每个Context创建自定义Hook,方便使用和类型检查
  6. 避免频繁更新的值:Context不适合频繁更新的状态(考虑使用状态管理库)

状态管理库有ReduxZustand 。Zustand 也是一个流行的 React 状态管理库,它以轻量、简单和灵活著称。