Skip to content

Props 与 State(数据传递)

React 基础速成

在 React 和 React Native 中,Props 和 State 是两个核心概念,它们用于管理组件的数据和行为。理解这两个概念对于开发 React Native 应用至关重要。

1. Props

Props(properties 的缩写)是组件的输入,它们是从父组件传递给子组件的数据。

基本概念

  • 只读性:Props 是只读的,子组件不能修改从父组件接收的 props
  • 可传递性:Props 可以从父组件传递到子组件,形成一个 props 链
  • 类型多样性:Props 可以是任何类型的数据,包括字符串、数字、布尔值、对象、数组,甚至是函数

使用 Props

传递 Props

jsx
// 父组件
import { View } from 'react-native';
import ChildComponent from './ChildComponent';

export default function ParentComponent() {
  return (
    <View>
      <ChildComponent 
        name="React Native" 
        age={30} 
        isActive={true} 
      />
    </View>
  );
}

接收 Props

jsx
// 子组件
import { View, Text } from 'react-native';

const ChildComponent = (props) => {
  return (
    <View>
      <Text>Name: {props.name}</Text>
      <Text>Age: {props.age}</Text>
      <Text>Is Active: {props.isActive ? 'Yes' : 'No'}</Text>
    </View>
  );
};

export default ChildComponent;

使用解构赋值

jsx
import { View, Text } from 'react-native';

const ChildComponent = ({ name, age, isActive }) => {
  return (
    <View>
      <Text>Name: {name}</Text>
      <Text>Age: {age}</Text>
      <Text>Is Active: {isActive ? 'Yes' : 'No'}</Text>
    </View>
  );
};

export default ChildComponent;

设置默认值

jsx
import { View, Text } from 'react-native';

const ChildComponent = ({ name = 'Default Name', age = 18, isActive = false }) => {
  return (
    <View>
      <Text>Name: {name}</Text>
      <Text>Age: {age}</Text>
      <Text>Is Active: {isActive ? 'Yes' : 'No'}</Text>
    </View>
  );
};

export default ChildComponent;

Props 传递函数

Props 不仅可以传递数据,还可以传递函数,这是子组件向父组件通信的主要方式。

jsx
// 父组件
import { View, Text, Button } from 'react-native';
import ChildComponent from './ChildComponent';
import { useState } from 'react';

export default function ParentComponent() {
  const [count, setCount] = useState(0);

  const handleIncrement = () => {
    setCount(count + 1);
  };

  return (
    <View>
      <Text>Count: {count}</Text>
      <ChildComponent onIncrement={handleIncrement} />
    </View>
  );
}

// 子组件
import { View, Button } from 'react-native';

const ChildComponent = ({ onIncrement }) => {
  return (
    <View>
      <Button title="Increment" onPress={onIncrement} />
    </View>
  );
};

export default ChildComponent;

2. State

State 是组件内部的状态数据,它用于管理组件的动态变化。

基本概念

  • 可变性:State 是可变的,组件可以修改自己的 state
  • 私有性:State 是组件私有的,其他组件无法直接访问
  • 响应性:当 state 发生变化时,组件会重新渲染

在函数组件中使用 State

在函数组件中,我们使用 useState Hook 来管理 state。

jsx
import { View, Text, Button } from 'react-native';
import { useState } from 'react';

export default function Counter() {
  // 声明一个名为 count 的 state 变量,初始值为 0
  const [count, setCount] = useState(0);

  return (
    <View>
      <Text>Count: {count}</Text>
      <Button 
        title="Increment" 
        onPress={() => setCount(count + 1)} 
      />
      <Button 
        title="Decrement" 
        onPress={() => setCount(count - 1)} 
      />
      <Button 
        title="Reset" 
        onPress={() => setCount(0)} 
      />
    </View>
  );
}

在类组件中使用 State

在类组件中,我们使用 this.statethis.setState() 来管理 state。

jsx
import React, { Component } from 'react';
import { View, Text, Button } from 'react-native';

class Counter extends Component {
  constructor(props) {
    super(props);
    this.state = {
      count: 0
    };
  }

  increment() {
    this.setState({ count: this.state.count + 1 });
  }

  decrement() {
    this.setState({ count: this.state.count - 1 });
  }

  reset() {
    this.setState({ count: 0 });
  }

  render() {
    return (
      <View>
        <Text>Count: {this.state.count}</Text>
        <Button title="Increment" onPress={() => this.increment()} />
        <Button title="Decrement" onPress={() => this.decrement()} />
        <Button title="Reset" onPress={() => this.reset()} />
      </View>
    );
  }
}

export default Counter;

State 的更新

函数式更新

当新的 state 依赖于旧的 state 时,应该使用函数式更新。

jsx
import { View, Text, Button } from 'react-native';
import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  // 函数式更新
  const increment = () => {
    setCount(prevCount => prevCount + 1);
  };

  return (
    <View>
      <Text>Count: {count}</Text>
      <Button title="Increment" onPress={increment} />
    </View>
  );
}

批量更新

React 会批量处理 state 更新,这意味着多个 setState 调用会在一次渲染中完成。

jsx
import { View, Text, Button } from 'react-native';
import { useState } from 'react';

export default function User() {
  const [name, setName] = useState('');
  const [age, setAge] = useState(0);

  const updateUser = () => {
    // 这两个更新会被批量处理
    setName('John');
    setAge(30);
  };

  return (
    <View>
      <Text>Name: {name}</Text>
      <Text>Age: {age}</Text>
      <Button title="Update User" onPress={updateUser} />
    </View>
  );
}

3. Props vs State

对比

特性PropsState
来源父组件传递组件内部定义
可变性只读可变
影响范围从父组件传递到子组件仅影响当前组件
初始化在组件调用时设置在组件内部初始化
更新方式父组件重新传递使用 setState 或 useState

何时使用 Props

  • 当数据需要从父组件传递到子组件时
  • 当数据在多个组件之间共享时
  • 当数据是静态的或由父组件控制时

何时使用 State

  • 当数据需要在组件内部管理时
  • 当数据会随着用户交互而变化时
  • 当数据只影响当前组件时

4. 状态提升

当多个组件需要共享同一个状态时,我们可以将状态提升到它们的共同父组件中。

jsx
import { View, Text, Button } from 'react-native';
import { useState } from 'react';

const ChildComponent1 = ({ count, onIncrement }) => {
  return (
    <View>
      <Text>Child 1 Count: {count}</Text>
      <Button title="Increment" onPress={onIncrement} />
    </View>
  );
};

const ChildComponent2 = ({ count }) => {
  return (
    <View>
      <Text>Child 2 Count: {count}</Text>
    </View>
  );
};

export default function ParentComponent() {
  const [count, setCount] = useState(0);

  const handleIncrement = () => {
    setCount(count + 1);
  };

  return (
    <View>
      <ChildComponent1 count={count} onIncrement={handleIncrement} />
      <ChildComponent2 count={count} />
    </View>
  );
}

5. 常见错误与解决方案

错误 1:修改 Props

错误

jsx
import { View, Text, Button } from 'react-native';

const ChildComponent = (props) => {
  const updateName = () => {
    props.name = 'New Name'; // 错误:不能修改 props
  };

  return (
    <View>
      <Text>Name: {props.name}</Text>
      <Button title="Update Name" onPress={updateName} />
    </View>
  );
};

export default ChildComponent;

解决方案

jsx
import { View, Text, Button } from 'react-native';

const ChildComponent = ({ name, onUpdateName }) => {
  const updateName = () => {
    onUpdateName('New Name'); // 正确:通过回调函数通知父组件
  };

  return (
    <View>
      <Text>Name: {name}</Text>
      <Button title="Update Name" onPress={updateName} />
    </View>
  );
};

export default ChildComponent;

错误 2:直接修改 State

错误

jsx
import { View, Text, Button } from 'react-native';
import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  const increment = () => {
    count++; // 错误:不能直接修改 state
    setCount(count);
  };

  return (
    <View>
      <Text>Count: {count}</Text>
      <Button title="Increment" onPress={increment} />
    </View>
  );
}

解决方案

jsx
import { View, Text, Button } from 'react-native';
import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1); // 正确:使用 setCount 更新 state
  };

  return (
    <View>
      <Text>Count: {count}</Text>
      <Button title="Increment" onPress={increment} />
    </View>
  );
}

错误 3:在渲染过程中更新 State

错误

jsx
import { View, Text } from 'react-native';
import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  // 错误:在渲染过程中更新 state
  setCount(count + 1);

  return (
    <View>
      <Text>Count: {count}</Text>
    </View>
  );
}

解决方案

jsx
import { View, Text, Button } from 'react-native';
import { useState } from 'react';

export default function Counter() {
  const [count, setCount] = useState(0);

  const increment = () => {
    setCount(count + 1); // 正确:在事件处理函数中更新 state
  };

  return (
    <View>
      <Text>Count: {count}</Text>
      <Button title="Increment" onPress={increment} />
    </View>
  );
}

6. 最佳实践

1. 保持 State 最小化

  • 只在 state 中存储必要的数据
  • 避免在 state 中存储可以通过计算得到的值
  • 考虑使用 useMemo 或 useCallback 优化计算

2. 状态管理策略

  • 对于简单的状态,使用 useState
  • 对于复杂的状态,考虑使用 useReducer 或状态管理库(如 Redux)
  • 对于跨组件共享的状态,使用 Context API 或状态管理库

3. Props 传递

  • 避免过度传递 props(prop drilling)
  • 对于深层嵌套的组件,考虑使用 Context API
  • 使用 TypeScript 或 PropTypes 来验证 props 类型

4. 性能优化

  • 使用 useCallback 缓存函数
  • 使用 useMemo 缓存计算结果
  • 对于大型列表,使用 React.memo 避免不必要的重新渲染

7. 总结

Props 和 State 是 React 和 React Native 中管理数据的核心概念:

  • Props:从父组件传递给子组件的数据,只读
  • State:组件内部管理的数据,可变

理解并正确使用 Props 和 State,是构建高质量 React Native 应用的关键。通过合理的状态管理和 props 传递,你可以创建出结构清晰、易于维护的应用。

下一节,我们将学习条件渲染和列表渲染,这是 React 中常用的渲染技术。

© 2026 编程马·菜鸟教程 版权所有