[React] Props
Published: 2023-06-26 13:34:37

## Props

- Values(properties) passed from a parent component
- They receive props as **arguments, similar to function arguments**, and **return React elements** that describe how the UI should be rendered based on those props
- You can pass **dynamic data (state) as well as static data**
- Props are **read-only objects**

### Pitfall
- Modifying props within a child component affects the value of the props passed by the parent component

-> This violates **the unidirectional, downward data flow principle of React**

-> It can lead to unintended side effects.

#### Side effects
: it refers to any modification or action that occurs outside the scope of the component rendering
- it happens  as a result of a component's execution, but not as a direct consequence of updating its state or props

**[e.g.]**
- Modifying the DOM directly using imperative APIs.
- Making AJAX requests or fetching data from an API.
- Subscribing to events or adding event listeners.
- Modifying shared state outside of the component, such as a global store.
- Timer or interval functions.

<br/>

## How to use props
- Regardless of the number of props, they are always **delivered in objects**
- After being passed from the parent component, it can be received through a parameter and then used
- To use the props, **use the dot notation method to read the value** (props is an object)

**[Parent Component]**
1) Define the values and attributes you want to pass to the child component

2) Pass the defined values and attributes using props
- 1 - Pass props to a React component similar to passing arguments to a function
- 2 - Place the value within the opening and closing tags to pass it

**[Child Component]**
3) Render the received props
- 1 - Access the value by using dot notation on the props object
- 2 - Access the value using props.children

**[e.g.1] Pass props to a React component**
```jsx
function Parent() {
  return (
    <div className="parent">
      <h1>I'm the parent</h1>
      // here
	  <Child text={"I'm the eldest child"} />
    </div>
  );
};

function Child(props) {
  return (
    <div className="child">
      //here	
      <p>{props.text}</p>
    </div>
  );
};
```

**[e.g.2] Place the value within the opening and closing tags**
```jsx
function Parent() {
  return (
    <div className="parent">
        <h1>I'm the parent</h1>
    	// here
        <Child>I'm the eldest child</Child>
    </div>
  );
};

function Child(props) {
  return (
    <div className="child">
    	// here
        <p>{props.children}</p>
    </div>
  );
};
```
<br/>

## Various types of props

#### 1. Primitive types: 
Such as strings, numbers, booleans, and null.

```jsx
<ChildComponent name="John" age={25} isStudent={true} />
```

#### 2. Objects: 
It's important to note that **objects are passed by reference**, so if the object changes in the parent component, it will affect the child component.

```jsx
const person = { name: "John", age: 25 };
<ChildComponent person={person} />
```

#### 3. Arrays: 

```jsx
const numbers = [1, 2, 3, 4, 5];
<ChildComponent numbers={numbers} />
```

#### 4. Functions: 
It is useful for passing callback functions from the parent component to the child component.

```jsx
const handleClick = () => {
  console.log('Button clicked!');
};
<ChildComponent onClick={handleClick} />
```

#### 5. React elements: 

```jsx
const title = <h1>Hello, world!</h1>;
<ChildComponent title={title} />
```
#### 6. Components
[Container.js]
- Style components passed as props using inline styles
```jsx
const Container=({children})=>{
//console.log(children);
//Symbol(react.element)
return (
	<div style={{margin:20, padding:20, border:"1px solid gray"}}>
	{children}
	</div>
	);
};
export default Container;
```
[App.js]
```jsx
import Container from "./Container";
...

function App(
...
	return(
		<Container>
			<div>
				<MyHeader/>
				<Counter {...counterProps}/>
			</div>
		</Container>
)
```
- The jsx elements placed between the components are passed to the Container component as a prop called children.

<br/>

## Practice
### 1. Render the passed props!
- Write code to render two strings by passing itemOne & itemTwo in the App component as props to the Learn component

```jsx
const App = () => {
  const itemOne = "I'm learning";
  const itemTwo = "React!";

  return (
    <div className="App">

    // pass the props
      <Learn text={itemOne} />
      <Learn> {itemTwo} </Learn>
    </div>
  );
};

const Learn = (props) => {
  //Rendering using passed props
  return (
    <div className="Learn">
      {props.text}
      {props.children}
    </div>
  );
};

export default App;

```

### 2. Pass the prop!
[App.js]
```jsx
import React from "react"
import Counter from "./Counter"

function App(){
	return (
		<div>
		<Counter initialValue={5}/> 
		</div>
	)
```
[Counter.js]
```jsx
import React, {useState} from "react"

const Counter=(props)=>{
//make sure you got it right
//console.log("props")

const [count, setCount]=useState(props.initialValue);

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

const onDecrease=()=>{
	setCount(count-1);
};

return (
	<div>
		<h2>{count}</h2>
		<button onClick={onIncrease}>+</button>
		<button onClick={onDecrease}>-</button>
	</div>
	)
};

export default Counter;
```

### 3. Pass the props!
- If there are many props that need to be passed, 
we can use spread operator to pass all the props.
- this allows us to pass an object containing multiple props without explicitly specifying each prop individually

[App.js]
```jsx
function App(){
	const counterProps={
	a:1,
	b:2,
	c:3,
	d:4,
	e:5,
	initialValue:5 ,
	};

	return (
		<div>
		<Counter {...counterProps}/>
		</div>
	)
```

[Counter.js]
```jsx
import React, {useState} from "react"
import OddEvenResult from "./OddEvenReslt"

const Counter=({initialValue})=>{

const [count, setCount]=useState({initialValue});

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

const onDecrease=()=>{
	setCount(count-1);
};

return (
	<div>
		<h2>{count}</h2>
		<button onClick={onIncrease}>+</button>
		<button onClick={onDecrease}>-</button>
		<OddEvenResult count={count}
	</div>
	)
};

export default Counter;
```
- Receive and use only necessary values ​from objects through destructing assignment
- The state of the count is being passed to the OddEvenResult component
- If props (initialValue) is not passed down from the parent component, but child component receives the props,
'undefined' is printed to the console.
→`const[count,setCount]=useState({initialValue}); `
Undefined is used as state value by code
→ NaN (error)


[Solution]
`Counter.defaultProps={
	initialValue:0
}`
- Error prevention by setting the default value of props that were not delivered through defaultProps value setting

[OddEvenResult.js]
- A component that determines whether count is odd or even
```jsx
const OddEvenResult=({count})=>{
	return<>{count%2===0?"짝수":"홀수"}</>
}  

export default OddEvenResult;
```

- re-rendering
React components re-render when their parent props change.
OddEvenResult renders a different result each time the Counter's state changes.
- Even if props are not passed from the parent element, when the parent element's state changes, the child element's component is also re-rendered.

#### Re-redering
- When the state value managed by the component changes
- When the props that come down to the child component change
- Even if neither of the above two cases, when its parent is re-rendered