[React] React Basic - (8) 정리

React Basic - (8) 정리

Food 예제

다양한 객체 선언 방식

const Food = ({fav, some, array}) => {
  return (
    <div>
      <h1>My Favorite food is {fav}</h1>
      <h2>{`This is ${some? 'true' : 'false'}`}</h2>
    </div>
  );
function Food(props) {
  return (
    <div>
      <h1>My Favorite food is {props.fav}</h1>
      <h2>This is {`${props.some? 'true' : 'false'}`}</h2>
    </div>
  );
function Food({ fav, img }) {
    return (
        <div>
            <h1>My Favorite food is {fav}</h1>
            <img src={img} />
        </div>
    );
}

map() 함수를 통해 배열을 다른 형태로 바꾸는 다양한 방식

  • 새로운 배열 생성 => map 내부에 arrow function 선언
const foodList = foodILike.map(food => (
    <Food fav={food.name} img={food.image} />
));
  • 새로운 배열 생성 => map 내부에 일반 function 선언
const foodList = foodILike.map(function(food) {
    return <Food fav={food.name} img={food.image} />;
});
  • return 내부에 바로 작성 ⇒ arrow function 사용
return (
	<div>
		{foodILike.map((dish)=> (
       <Food
        fav={dish.name}
        img={dish.image}
      />
    ))}
	</div>
);
...
  • return 내부에 바로 작성 ⇒ 외부 Function 사용
return (
	<div>
		{foodILike.map(renderFood)}
	</div>
);
...

function renderFood(dish) {
  return <Food key={dish.id} name={dish.name} img={dish.image}/>;
  // key는 객체의 prop으로 넣을 필요가 없다. 기본적으로 react 내부에서 사용하기 위한 것이기 때문
}
{console.log(foodILike.map(renderFood))}
        {/* ERROR: Each child in a list should have a unique "key" prop. */}
        {/* => 리스트의 모든 요소들은 유일한 key property를 가지고 있어야 함.*/}
해결 방법 : 배열의 각 요소에 id값을 부여한다.

전체 Code

import React from "react";
import PropTypes from "prop-types";

// 객체 선언 : 방법 1
/* const Food = ({fav, some, array}) => {
  return (
    <div>
      <h1>My Favorite food is {fav}</h1>
      <h2>{`This is ${some? 'true' : 'false'}`}</h2>
    </div>
  );
} */

// 객체 선언 : 방법 2
/* function Food(props) {
  return (
    <div>
      <h1>My Favorite food is {props.fav}</h1>
      <h2>This is {`${props.some? 'true' : 'false'}`}</h2>
    </div>
  );
} */

// 객체 선언 : 방법 3
function Food({ fav, img, rating }) {
    return (
        <div>
            <h1>My Favorite food is {fav}</h1>
            <h4>{rating}/5.0</h4>
            <img src={img} />
        </div>
    );
}

Food.propTypes = {
    /*  각 prop 요소가 가져야 하는 형태를 정의함
  : PropTypes를 통해 각 prop의 형태 / 존재 여부를 체크할 수 있음 */
    name: PropTypes.string.isRequired,
    image: PropTypes.string.isRequired,
    // => .isRequired 가 없으면 undefined도 가능

    /* rating: PropTypes.string.isRequired
  => rating이 string이어야 함. but 위 배열에서는 rating이 숫자로 표시되어 있기 때문에 console에서 ERROR 발생 */
    rating: PropTypes.number.isRequired
};
// return 안에 들어가는 {}는 모두 JSX임

const foodILike = [
    {
        id: 1,
        name: "chicken",
        image:
            "https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse1.mm.bing.net%2" +
            "Fth%3Fid%3DOIP.mIpo5pgFWyhPe1Iin4I8yQHaFF%26pid%3DApi&f=1",
        rating: 5
    },
    {
        id: 2,
        name: "pork belly",
        image:
            "https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse1.mm.bing.net%2" +
            "Fth%3Fid%3DOIP.UmVEcfZCr9vDfLdcnDyoLAHaFj%26pid%3DApi&f=1",
        rating: 4
    },
    {
        id: 3,
        name: "milkshake",
        image:
            "https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse1.mm.bing.net%2" +
            "Fth%3Fid%3DOIP.szKYcXQeNsJiTp6ScAw2mwHaEw%26pid%3DApi&f=1",
        rating: 3
    },
    {
        id: 4,
        name: "sushi",
        image:
            "https://external-content.duckduckgo.com/iu/?u=https%3A%2F%2Ftse1.mm.bing.net%2" +
            "Fth%3Fid%3DOIP._1YtdtHAiKCeGlC1piszvgHaEv%26pid%3DApi&f=1",
        rating: 4.5
    }
];

function App() {
    // map : 방법 1 (새로운 배열 생성 => map 내부에 arrow function 선언)
    /*   const foodList = foodILike.map(
    (food) =>(
      <Food
        fav={food.name}
        img={food.image}
      />
    )
  ); */
    // map : 방법 2 (새로운 배열 생성 => map 내부에 일반 function 선언)
    /*  const foodList = foodILike.map(function(food) {
    return (
      <Food
        fav={food.name}
        img={food.image}
      />
    )
  }); */
    return (
        <div>
            {/* map : 방법 3 (arrow function 사용) */}
            {/* {foodILike.map((dish)=> (
         <Food
          fav={dish.name}
          img={dish.image}
        />
       ))} */}

            {/* map : 방법 4 (외부 Function 사용)*/}
            {console.log(foodILike.map(renderFood))}
            {/* ERROR: Each child in a list should have a unique "key" prop. */}
            {/* => 리스트의 모든 요소들은 유일한 key property를 가지고 있어야 함.*/}

            {foodILike.map(renderFood)}
        </div>
    );
}
function renderFood(dish) {
    return (
        <Food
            key={dish.id}
            name={dish.name}
            img={dish.image}
            rating={dish.rating}
        />
    );
    // key는 객체의 prop으로 넣을 필요가 없다. 기본적으로 react 내부에서 사용하기 위한 것이기 때문
}

export default App;

State & Component Life Cycle

React Component

  • Component에는 render(), state 등 많은 컴포넌트 요소들이 포함되어 있다.
  • 'Component'를 extend 하면 react는 자동적으로 class Component의 render() 함수를 실행한다.

setState()

  • state의 속성

    1. state는 object이다.
    2. state에는 Component의 data를 넣을 수 있다.
    3. state는 변한다.
  • state를 명시적으로 직접 변경해선 안된다. 대신, setState()를 사용해야 한다.
  • 이유 : state는 객체이므로, 변경 시 원래 state 값에서 업데이트된 새로운 state 객체를 생성해야 한다.
  • 매번 setState() 를 호출할 때마다 react는 새로운 state와 함께 render()를 호출한다.
  • setState()를 통해 react는 rendering할 때 변화가 있는 부분만 감지하여 업데이트한다. ⇒ "Virtual DOM"의 특성
// 방법 1
this.setState({
    count: this.state.count + 1
});
// => 권장하지 않는 방식.

// 방법 2
this.setState(current => ({
    count: current.count++
}));
// react가 기본적으로 제공하는 current 변수 이용.

render() 함수에서의 state 사용

// 방법 1
return <div>{this.state.isLoading ? "Loading" : "We are ready"}</div>;
// 방법 2 => ES6
const { isLoading } = this.state;
return <div>{isLoading ? "Loading..." : "We are ready"}</div>;

Component Life Cycle

  • Mounting : 컴포넌트가 생성되고 DOM에 입력될 때 호출되는 함수

    • 호출 순서
    • constructor()
    • render()
    • componentDidMount() : 컴포넌트가 처음 렌더링되었는지 알려줌
  • Update : state 등 컴포넌트가 변경될 때 호출되는 함수

    • shouldComponentUpdate() : 조건이 true일 때만 컴포넌트를 업데이트하도록 정의
    • render()
    • componentDidUpdate() : 컴포넌트가 업데이트된 후(render() 함수가 호출된 후)에 호출됨.
  • Unmounting : 컴포넌트가 DOM에서 제거될 때 호출되는 함수

    • componentWillUnmount() : 다른 페이지로 이동할 때, 페이지를 닫을 때와 같이 컴포넌트가 Unmount되기 직전에 호출됨.

setTimeout()

일정 시간 후에 state가 변하도록 설정

setTimeout(
    () =>
        this.setState({
            isLoading: false
        }),
    3000
);
// 3초 후에 isLoading이 false로 변경됨.

전체 Code

import React from "react";

class App extends React.Component {
    state = {
        count: 0
    };
    constructor(props) {
        super(props);
        console.log("constructor called");
    }
    add = () => {
        this.setState(current => ({
            count: current.count++
        }));
    };
    minus = () => {
        this.setState({
            count: this.state.count - 1
        });
    };
    render() {
        console.log("I'm rendering");
        return (
            <div>
                <h1>The number is {this.state.count}</h1>
                <button onClick={this.add}>Add</button>
                <button onClick={this.minus}>Minus</button>
            </div>
        );
    }
    componentDidMount() {
        console.log("component rendered");
    }
    componentDidUpdate() {
        console.log("I just updated");
    }
}
export default App;