Props (skrót od "properties", czyli właściwości) są fundamentalnym mechanizmem przekazywania danych między komponentami w React. Możesz myśleć o nich jak o argumentach funkcji - pozwalają na wprowadzanie danych do komponentu z zewnątrz.
Props są przekazywane do komponentu jako pojedynczy obiekt. W komponentach funkcyjnych, ten obiekt jest zwykle pierwszym parametrem funkcji:
1function MissionInfo(props) {
2 return (
3 <div className="mission-info">
4 <h2>{props.name}</h2>
5 <p>Status: {props.status}</p>
6 <p>Rozpoczęcie: {props.startDate}</p>
7 </div>
8 );
9}
10
11// Użycie
12<MissionInfo
13 name="Apollo 11"
14 status="Zakończona"
15 startDate="16 lipca 1969"
16/>Jedną z największych zalet React jest możliwość tworzenia złożonych interfejsów poprzez komponowanie mniejszych, wielokrotnego użytku komponentów. Props są kluczowe w tym procesie, ponieważ umożliwiają komunikację między tymi komponentami.
Najczęstszym kierunkiem przepływu danych w React jest z góry na dół - od komponentów rodzicielskich do komponentów potomnych:
1function SpaceProgram() {
2 const missionData = {
3 id: 'apollo11',
4 name: 'Apollo 11',
5 crew: ['Neil Armstrong', 'Buzz Aldrin', 'Michael Collins'],
6 launchDate: '16 lipca 1969',
7 status: 'Zakończona'
8 };
9
10 return (
11 <div className="space-program">
12 <h1>Program Kosmiczny</h1>
13 <Mission
14 name={missionData.name}
15 crew={missionData.crew}
16 launchDate={missionData.launchDate}
17 status={missionData.status}
18 />
19 </div>
20 );
21}
22
23function Mission({ name, crew, launchDate, status }) {
24 return (
25 <div className="mission">
26 <h2>{name}</h2>
27 <p>Data startu: {launchDate}</p>
28 <p>Status: {status}</p>
29 <CrewList crew={crew} />
30 </div>
31 );
32}
33
34function CrewList({ crew }) {
35 return (
36 <div className="crew-list">
37 <h3>Załoga:</h3>
38 <ul>
39 {crew.map((member, index) => (
40 <li key={index}>{member}</li>
41 ))}
42 </ul>
43 </div>
44 );
45}W tym przykładzie:
SpaceProgram zawiera dane misjiMissionMission przekazuje dodatkowo tablicę crew do komponentu CrewListZamiast korzystać z
props.nazwa, w nowoczesnym JavaScript powszechnie stosuje się destrukturyzację, co czyni kod bardziej czytelnym:1// Zamiast:
2function Astronaut(props) {
3 return (
4 <div>
5 <h3>{props.name}</h3>
6 <p>Rola: {props.role}</p>
7 <p>Misje: {props.missions}</p>
8 </div>
9 );
10}
11
12// Lepiej:
13function Astronaut({ name, role, missions }) {
14 return (
15 <div>
16 <h3>{name}</h3>
17 <p>Rola: {role}</p>
18 <p>Misje: {missions}</p>
19 </div>
20 );
21}PropTypes to system do sprawdzania typów props podczas rozwoju aplikacji. Pomaga wyłapywać błędy związane z przekazywaniem nieprawidłowych danych do komponentów.
1import PropTypes from 'prop-types';
2
3function LaunchButton({ onClick, isEnabled, label }) {
4 return (
5 <button
6 onClick={onClick}
7 disabled={!isEnabled}
8 className="launch-button"
9 >
10 {label || 'Start'}
11 </button>
12 );
13}
14
15LaunchButton.propTypes = {
16 onClick: PropTypes.func.isRequired,
17 isEnabled: PropTypes.bool,
18 label: PropTypes.string
19};
20
21LaunchButton.defaultProps = {
22 isEnabled: true
23};Dostępne są różne typy walidatorów:
Możesz ustawić domyślne wartości dla props na wypadek, gdyby nie zostały przekazane:
1function Countdown({ seconds, color }) {
2 return (
3 <div style={{ color }}>
4 T-minus: {seconds} sekund
5 </div>
6 );
7}
8
9Countdown.defaultProps = {
10 seconds: 10,
11 color: 'red'
12};W nowszych wersjach React można też używać domyślnych wartości bezpośrednio w destrukturyzacji:
1function Countdown({ seconds = 10, color = 'red' }) {
2 return (
3 <div style={{ color }}>
4 T-minus: {seconds} sekund
5 </div>
6 );
7}Jednym z najważniejszych zastosowań props jest przekazywanie funkcji, które pozwalają dziecku komunikować się z rodzicem:
1function MissionControl() {
2 const handleLaunch = () => {
3 alert('Odpalenie rakiety!');
4 };
5
6 return (
7 <div className="mission-control">
8 <h2>Centrum Kontroli Misji</h2>
9 <LaunchPad onLaunch={handleLaunch} />
10 </div>
11 );
12}
13
14function LaunchPad({ onLaunch }) {
15 return (
16 <div className="launch-pad">
17 <h3>Platforma startowa</h3>
18 <button onClick={onLaunch}>
19 Rozpocznij odliczanie i wystrzel
20 </button>
21 </div>
22 );
23}W tym przykładzie komponent potomny
LaunchPad może wywołać funkcję przekazaną przez rodzica, co pozwala na komunikację "w górę".Jeśli masz obiekt zawierający wiele właściwości, które chcesz przekazać jako props, możesz użyć operatora spread:
1function App() {
2 const rocketProps = {
3 name: 'Falcon Heavy',
4 manufacturer: 'SpaceX',
5 height: '70 m',
6 thrust: '22,819 kN'
7 };
8
9 return (
10 <div className="app">
11 <h1>Informacje o rakiecie</h1>
12 <Rocket {...rocketProps} />
13 </div>
14 );
15}
16
17function Rocket({ name, manufacturer, height, thrust }) {
18 return (
19 <div className="rocket">
20 <h2>{name}</h2>
21 <ul>
22 <li>Producent: {manufacturer}</li>
23 <li>Wysokość: {height}</li>
24 <li>Ciąg: {thrust}</li>
25 </ul>
26 </div>
27 );
28}Specjalny prop
children zawiera wszystko, co jest umieszczone między tagami otwierającym i zamykającym komponentu:1function Card({ title, children }) {
2 return (
3 <div className="card">
4 <div className="card-header">
5 <h3>{title}</h3>
6 </div>
7 <div className="card-body">
8 {children}
9 </div>
10 </div>
11 );
12}
13
14// Użycie
15function App() {
16 return (
17 <Card title="Status misji">
18 <p>Wszystkie systemy działają prawidłowo.</p>
19 <button>Więcej szczegółów</button>
20 </Card>
21 );
22}Bardzo ważne jest zrozumienie, że props są tylko do odczytu. Komponent nie powinien nigdy modyfikować swoich własnych props. Takie zachowanie narusza zasadę "jednokierunkowego przepływu danych" w React.
1// ŹLE - nigdy nie modyfikuj props!
2function BadComponent(props) {
3 props.value = 42; // Błąd!
4 return <div>{props.value}</div>;
5}
6
7// DOBRZE - używaj props tylko do odczytu
8function GoodComponent(props) {
9 return <div>{props.value}</div>;
10}Jeśli potrzebujesz zmiennego stanu na podstawie props, możesz użyć
useState z początkową wartością opartą na props:1function Counter({ initialCount }) {
2 const [count, setCount] = useState(initialCount);
3
4 return (
5 <div>
6 <p>Licznik: {count}</p>
7 <button onClick={() => setCount(count + 1)}>
8 Zwiększ
9 </button>
10 </div>
11 );
12}Props są podstawowym mechanizmem komunikacji między komponentami w React. Pozwalają na:
Dobrą praktyką jest:
W kolejnych sekcjach nauczymy się, jak uzupełnić props o stan (state), aby tworzyć w pełni interaktywne komponenty.