React Native - Props
React Native - Props
Section titled “React Native - Props”In React, components communicate and share data primarily through props (short for properties). Props are read-only and are passed from parent components to child components, allowing for data flow in one direction (unidirectional data flow).
This chapter builds upon our understanding of state by demonstrating how to pass data and functions as props, often distinguishing between ‘container’ (smart) components that manage state and logic, and ‘presentational’ (dumb) components that primarily display data.
Parent (Container) Component Managing State
Section titled “Parent (Container) Component Managing State”Let’s create a parent component that holds some state and a function to update that state. It will then pass this state and function down to a child component via props.
ParentComponent.js
import React, { useState } from 'react';import { View, StyleSheet, Text } from 'react-native';import ChildDisplayComponent from './ChildDisplayComponent'; // We'll create this next
const ParentComponent = () => { const [greeting, setGreeting] = useState('Hello from Parent!'); const [count, setCount] = useState(0);
const updateGreeting = (newGreeting) => { setGreeting(newGreeting); };
const incrementCount = () => { setCount(prevCount => prevCount + 1); };
return ( <View style={styles.container}> <Text style={styles.parentText}>Parent Component Area</Text> <ChildDisplayComponent message={greeting} currentCount={count} onUpdateGreeting={updateGreeting} // Pass the function itself onIncrement={incrementCount} // Pass the function itself user={{ name: 'Alice', role: 'Admin' }} // Pass an object as a prop /> </View> );};
const styles = StyleSheet.create({ container: { flex: 1, padding: 20, backgroundColor: '#e0f7fa', alignItems: 'center', }, parentText: { fontSize: 20, fontWeight: 'bold', marginBottom: 15, color: '#00796b', }});
export default ParentComponent;In ParentComponent.js:
- We use
useStateto managegreetingandcount. updateGreetingandincrementCountare functions that modify this state.- We render
ChildDisplayComponentand pass downgreeting(asmessage),count(ascurrentCount),updateGreeting(asonUpdateGreeting),incrementCount(asonIncrement), and auserobject as props.
Child (Presentational) Component Receiving Props
Section titled “Child (Presentational) Component Receiving Props”Now, let’s create the ChildDisplayComponent. This component will receive data and functions through its props and use them to render UI and trigger actions in the parent.
ChildDisplayComponent.js
import React from 'react';import { Text, View, Button, StyleSheet } from 'react-native';import PropTypes from 'prop-types'; // Recommended for type checking props
// Props are received as the first argument (typically named 'props')// We can destructure them directly in the function signatureconst ChildDisplayComponent = ({ message, currentCount, onUpdateGreeting, onIncrement, user }) => { return ( <View style={styles.childContainer}> <Text style={styles.messageText}>Message from parent: {message}</Text> <Text style={styles.countText}>Current Count: {currentCount}</Text> <Text style={styles.userInfo}>User: {user.name} ({user.role})</Text>
<Button title="Update Greeting in Parent" onPress={() => onUpdateGreeting('Hello from Child!')} /> <View style={{ marginTop: 10 }} /> {/* Simple spacer */} <Button title="Increment Count in Parent" onPress={onIncrement} // Call the function passed via props /> </View> );};
// PropTypes define the type of props your component expects.// This is good practice for catching bugs and for documentation.ChildDisplayComponent.propTypes = { message: PropTypes.string.isRequired, currentCount: PropTypes.number.isRequired, onUpdateGreeting: PropTypes.func.isRequired, onIncrement: PropTypes.func.isRequired, user: PropTypes.shape({ name: PropTypes.string.isRequired, role: PropTypes.string }).isRequired};
// Default props can be defined if some props are not always passedChildDisplayComponent.defaultProps = { user: { name: 'Guest', role: 'Viewer' } // This would be used if 'user' prop isn't provided};
const styles = StyleSheet.create({ childContainer: { marginTop: 20, padding: 15, backgroundColor: '#ffffff', borderWidth: 1, borderColor: '#004d40', borderRadius: 8, alignItems: 'center', }, messageText: { fontSize: 18, color: '#00796b', marginBottom: 10, }, countText: { fontSize: 18, color: '#00796b', marginBottom: 10, }, userInfo: { fontSize: 16, color: '#333', marginBottom: 20, }});
export default ChildDisplayComponent;In ChildDisplayComponent.js:
- It receives
message,currentCount,onUpdateGreeting,onIncrement, anduseras props. - It displays the
message,currentCount, anduserdata. - The buttons, when pressed, call the functions (
onUpdateGreeting,onIncrement) passed down from the parent. This allows the child to trigger state changes in the parent.
When you run the ParentComponent, it will render the ChildDisplayComponent. The child will display the initial greeting and count. Clicking the buttons in the child component will call functions in the parent, update the parent’s state, and cause both components to re-render with the new data.
Key Concepts of Props
Section titled “Key Concepts of Props”- Read-Only: A component must never modify its own props. They are owned by the parent.
- Data Flow: Data flows down from parent to child. To change data in the parent from a child, pass a callback function from the parent to the child.
- PropTypes: Using the
prop-typeslibrary (or TypeScript) to define expected prop types is highly recommended for larger applications to catch errors early. - Default Props: You can define default values for props if they are not provided by the parent.
This pattern of container components managing state and logic, and presentational components focusing on UI and receiving data via props, helps in creating more maintainable and reusable React Native applications. Read more on components and props: https://react.dev/learn/passing-props-to-a-component