WEB, ReactJS, Component State

State

  • 리액트 컴포넌트 안에 있는 오브젝트
  • state가 바뀔 때 마다, 컴포넌트는 새로운 state와 함께 다시 render한다
  • setState : state를 직접 수정하지 않는다. setState를 이용해서 수정한다.
  • ex. hello를 출력하고, 2초후에 hello again!으로 수정(setState)되어 출력(render)된다.
class App extends React.Component {

  state = {
    greeting : "Hello"  
  }
  // Render : 1.componentWillMount() 2.render() 3.componentDidMount()
  componentDidMount() {
    setTimeout(() => {
      // state를 직접 수정하지 않는다
      // ex. state.greeting = "hello again!"
      this.setState({
        greeting : "hello again!"
      })
    }, 2000)
  }
  render() {
    return (
      <div className="App">
       {this.state.greeting}
       {movies.map( (movie, index) => {
        return <Movie title={movie.title} poster={movie.poster} key={index} />
      })}
      </div>
      );
    }
}
  • 참고 ) setTimeout(function(){}, 1000) –new version–> setTimeout(()=> , 1000)

…this.state.movies

  • state에 새로운 내용 추가시에 …this.state.movies를 적절히 활용한다
  • …this.state.movies : 현재 state.movies내용
state = {
  movies: [
    {
      title: "Harry Poter",
      poster: "https://t1.daumcdn.net/thumb/R720x0/?fname=http://t1.daumcdn.net/brunch/service/user/5xq2/image/w2gbbJ7lwG0quKMZtTihufPuvno.jpg"
    },
    {
      title: "Toy Story",
      poster: "https://t1.daumcdn.net/thumb/R720x0/?fname=http://t1.daumcdn.net/brunch/service/user/5uYQ/image/R3t_QxnFFfr20i8ekqVdzxUnBYE.jpg"
    },
    {
      title: "Aladin",
      poster: "http://img.movist.com/?img=/x00/05/11/49_p1.jpg"
    }
  ]
}

componentDidMount() {
  setTimeout(() => {
    this.setState({
      movies: [  
        // movies state에 이전 리스트
        ...this.state.movies,
        // 아래의 리스트를 추가한다
        {
          title: "Inside Out",
          poster: "http://t1.daumcdn.net/movie/0c0ae692e5a1f4cc79704eb09d21a835b40f567d"
        },

      ]
    })
  }, 1000)
}

결과

  • 1초 후에 이전의 movies 리스트에 새로운 항목이 추가되어 나타난다.

reactjs state


Loding states

  • 필요한 데이터는 항상 즉시 존재하지는 않는다
  • 데이터 로드 과정
    • 데이터 없이 컴포넌트가 로딩을한다
    • API를 호출하여 데이터를가져온다.
    • 가져온 데이터를 이용해 컴포넌트 state를 업데이트한다
  • 오류 발생
    • state가 비어있는데 (데이터 로드가 아직 안됨) state의 항목을 출력하려고 시도 하면 오류가 발생한다.
  • 오류 해결 방법
    • 호출하려는 항목이 state에 없으면, “Loading” 등의 글을 출력하고
    • 호출하려는 항목(데이터)가 로드 되면 그때 출력한다.
      {this.state.movies ? this._renderMovies() : "Loading"}
      

전체코드

import React, { Component } from 'react';
import Movie from './Movie';
import './App.css';


class App extends React.Component {
  state = {

  }
  componentDidMount() {
    setTimeout(() => {
      this.setState({
        movies: [
          {
            title: "Harry Poter",
            poster: "https://t1.daumcdn.net/thumb/R720x0/?fname=http://t1.daumcdn.net/brunch/service/user/5xq2/image/w2gbbJ7lwG0quKMZtTihufPuvno.jpg"
          },
          {
            title: "Toy Story",
            poster: "https://t1.daumcdn.net/thumb/R720x0/?fname=http://t1.daumcdn.net/brunch/service/user/5uYQ/image/R3t_QxnFFfr20i8ekqVdzxUnBYE.jpg"
          },
          {
            title: "Aladin",
            poster: "http://img.movist.com/?img=/x00/05/11/49_p1.jpg"
          },
          {
            title: "Inside Out",
            poster: "http://t1.daumcdn.net/movie/0c0ae692e5a1f4cc79704eb09d21a835b40f567d"
          }
        ]
      })
    }, 3000)
  }

  // 함수로 빼버림
  _renderMovies = () => {
    // movies라는 변수에 데이터 저장
    const movies = this.state.movies.map((movie, index) => {
      return <Movie title={movie.title} poster={movie.poster} key={index} />
    })
    return movies
  }

  // state에 movies가 없기 때문에 state.movies를 출력하라는 코드는 에러가 난다.
  // 해결 방법 -> movies가 없으면 "Loading"출력, 있으면 movies출력
  render() {
    return (
      <div className="App">
        {this.state.movies ? this._renderMovies() : "Loading"}
      </div>
    );
  }
}
export default App;
  • tip) _renderMovies 함수에서 _를 사용하는 이유
    • 리액트는 자체 기능이 많기 때문에 리액트 자체기능과 나의 기능에 차이를 두려고 ‘_‘를 사용한다

Reference

https://www.inflearn.com/course/reactjs-web/lecture/8284 https://www.inflearn.com/course/reactjs-web/lecture/8285 https://www.inflearn.com/course/reactjs-web/lecture/8286