[DEV] 02 - 이터러블 / 이터레이터 (함수형프로그래밍 es06)

headerimg 함수형 프로그래밍과 javascript es6를 깊게 파보기.

이터러블(Iterable) / 이터레이터(Iterator) 프로토콜

이터러블(Iterable) 순회 가능한 객체를 가르키는 말. for of는 대부분 배열의 순회에 사용 된다고 알고 있지만 사실 순회가능(iterable)한 모든 객체를 대상으로 사용할 수 있다.

어떤 것이 이터러블 일까? Symbol.iterator 심볼 속성을 가지고 있고 이터레이터 객체를 반환하는 객체 말한다. 이런 스펙을 이터러블 프로토콜이라 하고 이 객체를 이터러블 객체라고 한다.

이터레이터(Iterator) 위에 서 말한 이터러블한 객체가 [Symbol.interator]() 메소드로 반환하는 객체를 이터레이터 라고 한다. 이터레이터는 next() 메소드와 done, value 객체을 가진 객체이고 이 스펙을 이터레이터 프로토콜이라고 한다.

정리

  • 이터러블 : 이터레이터를 반환하는 [Symbol.iterator]()를 가진 값.
  • 이터레이터 : { value, done } 객체를 리턴하는 next()를 가진 값.
  • 이터러블/이터레이터 프로토콜 : 이터러블과 for of 등과 함께 사용할 수 있도록한 규약
const num = [1,2,3,4]; //이터러블

imgG

console.log(num);에 __proto__에 들어있는 심볼 이터레이터


imgG

arr는 이터러블이고 이터레이터를 반환한다.

커스텀 이터러블, 이터레이터 프로토콜 정의

사용자 정의 이터러블, 이터레이터를 만들어보면 속사정이 이해가 쉽다.

const arr = [1,2,3];
let iter1 = arr[Symbol.iterator]();
iter1.next();
for(const a of iter1) console.log(a);
/*
2
3
*/


const iterable = {
    [Symbol.iterator](){
        let i = 1;
        return{
            next(){
                return i > 3 ? { value: undefined, done: true } : { value: i++, done: false };
            },
            [Symbol.iterator]() { return this; }
        }
    }
}
let iterator = iterable[Symbol.iterator]();
console.log(iterator.next()); // {value: 1, done: false}
console.log(iterator.next()); // {value: 2, done: false}
console.log(iterator.next()); // {value: 3, done: false}
console.log(iterator.next()); // {value: undifined, done: true} done이 ture가 되면 멈춘다.
for(const a of iterator) console.log(a);
/*
1
2
3
*/

와.. 그래 그래

그래서.. for of 돌릴라고 이런걸 만든건가? 아니겠지
이터러블/이터레이터 ( 이터레이션 ) 프로토콜은 for-of, spread(전개연산자), Map/Set 생성자 등에 사용된다. 그 대상 데이터들은 배열, 문자열, Map/Set, Dom을 사용할 수 있다.

[DEV] 01 - 기본기 (함수형프로그래밍 es06)

headerimg 함수형 프로그래밍과 javascript es6를 깊게 파보기.

기본기

angularJS를 사용하다 es06를 접해 접목해보고 react, vue 등의 프레임워크를 공부하다 보니 JS 기본기가 부족한 것이 많이 느껴졌다. 면접에서도 그렇고.. 언뜻 느낌적인 느낌만 알고만 있는 함수형 프로그래밍과 es06에 대해 탄탄한 기본기를 기르기 위해

평가

  • 코드가 계산(Evaluation) 되어 값을 만드는 것
1 // 1
1 + 2 // 3
(1 + 5) + 5 //  11
[1, 2, ...[3, 4]] // [1, 2, 3, 4]

일급(first-class)

  • 값으로 다룰 수 있다.
  • 변수에 담을 수 있다.
  • 함수의 인자로 사용될 수 있다.
  • 함수의 결과로 사용될 수 있다.
const foo = 10; // 값으로 다룰 수 있고, 변수에 담을 수 있다.
const add10 = num => num + 10; 
// 함수의 인자로 num이 전달(사용) 될 수 있고
// 함수의 결과(리턴)으로 사용될 수 있다.

const bar = add10(20);
console.log(bar); // 30

일급 함수

  • JS에서는 함수는 일급이다.
  • 함수를 값으로 다룰 수 있다.
  • 조합성과 추상화의 도구
  • 함수를 다른 변수와 동일하게 다루는 언어는 일급 함수를 가졌다고 표현합니다. 예를 들어, 일급 함수를 가진 언어에서는 함수를 다른 함수에 매개변수로 제공하거나, 함수가 함수를 반환할 수 있으며, 변수에도 할당할 수 있습니다. (by MDN)
const add7 = a => a + 7; // 변수에 함수를 값으로 담을 수 있다.
console.log(add7);  // 다른함수(console.log)의 인자로 사용 될 수 있다.
console.log(add7(3)); // 함수를 평가해서 값으로 만들 수 있다.

const f1 = () => () => 1; //함수의 결과로 함수를 사용할 수 있다.
console.log(f1()); 

const f2 = f1();
console.log(f2);
console.log(f2()); 

고차 함수

  • 함수를 값으로 다루는 함수.

    고차함수에는 두 가지 유형이 있다.


함수를 인자로 받아서 실행하는 함수

const apply1 = f => f(1); 
// 고차함수 apply1
// 함수(apply1)가 함수를 인자로 받아서 1을 f의 인자 값으로 주는 함수. 

const add2 = a => a + 2;

console.log(apply1(add2)); // 3
console.log(apply1(a=>a-1)); // 0

const times = (f, n) => { // 함수를 값으로 받고.
    let i = -1;
    while(++i < n) f(i));
}

times(console.log, 3)
// 0
// 1
// 2

times(a => console.log(a + 10), 3)
// 10
// 11
// 12


함수를 만들어 리턴하는 함수

const addMaker = a => b => a + b;
/*
b => a + b 함수는 클로저이다. 
반환된 내부함수(a => a+ b)가 자신이 선언될 때, 렉시컬 환경(스코프)을 기억해(a가 10), 
렉시컬 환경 밖에서 호출되어도 그 렉시컬 환경(a가 10)에 접근 할 수 있는 함수가 클로저.
*/
const add10 = addMaker(10);

console.log(add10(5)); // 15
console.log(add10(10)); // 20


참고
렉시컬 환경 : 컴파일러는 코드를 실행하는 첫 단계에 토크나이징/렉싱 이라는 작업을 한다.
var a = b; 에서
var
a
=
b
;
식으로 토큰화하여 의미를 부여하는 것을 렉싱이라 한다. 이 렉싱 단계에서 모든 변수들이 어떻게 선언되었는지 실행단계에서 스코프를 구성하는데 이게 렉시컬 환경(스코프) 이다.

var 자제 해야 하는 이유.

  1. 함수 레벨 스코프
    • 어떤 함수 외부에 작성되면 전역화 되기 쉬움.
    • for나 if 안에서 선언된 var 변수는 블록 밖에서 참조할 수 있다.
  2. 변수를 중복 선언 가능
    • 이름만 같은 변수들이 생겨 값이 달라질 수 있다.
  3. 호이스팅
    • 선언하기 전에 참조 가능성이 있다.
  4. 전역으로 선언 시 윈도우 전역 객체에 프로퍼티가 된다.
    • var suck = 10;
    • console.log(window.suck) // 10

var의 단점을 정리하면 스코프 범위가 넓어서 생기는 문제와 의도치 않은 사용들로 버그가 발생의 원인이 될 수 있다.

let의 장점

  1. 블록 레벨 스코프
    • 가까운 중괄호 안에서만 유효한 작은 스코프이기 때문에 관리하기 쉽다.
  2. 중복 선언 금지
    • 중복 선언이 금지되어 원하는 값을 유지할 수 있다.
  3. 호이스팅
    • 호이스팅이 되지 않아 선언하기 전에 참조 가능성이 적다.
    • 사실 호이스팅이 되긴한다. (응?)
    • 참고 : TDZ(Temporal Dead Zone)를 검색!

const 장점

  1. 재할당이 금지된다.
    • 변하지 않는 상수를 써야할 때는 const에 할당하면 값이 바뀌지 않아 편하다.
    • ex: const minutes = 60000;
  2. 객체
    • 객체가 const에 할당될 경우 재할당이나 참조를 변경하는 경우는 금지된다.
    • 하지만 프로퍼티의 추가, 삭제, 값의 변경은 가능하다.
const user = { age: 20 };
user.age = 25;
console.log(user); // { age: 25 }
delete user.age;
console.log(user); // {}

정리! 코딩 할때 마음가짐

  1. 변수를 할당 할 때, 우선순위로 const, 만약 재할당이 이루어지면 let 을 사용하자.
  2. var는 잊어버리거나 es6를 사용할 수 없으면 .. ?
  3. 객체에는 const를 사용한다. (객체를 재할당하는 경우는 찾기 힘들다.)

[DEV] react styled components 간단하게 개념잡기

headerimg

경고

공부기록용임. 코드나 커리큘럼 방식 등 모든 지적 재산권은 노마드 코더에게 있으며, 무료로 볼 수 있으니 들어가서 여기서 공부할 것!! 갓 니콜라이 노마드 코더님 만세! https://academy.nomadcoders.co

CSS SCSS는?

CSS 시절
Button이 만약 3가지가 있다면

<button className="button">Button</button>
<button className="button button--success">Success</button>
<button className="button button--danger">Danger</button>
.button{
    border: none;
    padding: 1rem 2rem;
    background-color: gray;
    cursor: pointer;
    font-weight: bold;
    color: white;
    margin-right: 1rem;
}
.button--success{
    background-color: #27ae60;
}
.button--danger{
    background-color: #c0392b;
}

이런식으로 쓰게된다. SCSS or SASS에서는 크게 달라지지 않지만 그래도 많이 줄일 수 있다.

SCSS 시절

<button className="button">Button</button>
<button className="button success">Success</button>
<button className="button danger">Danger</button>
.button{
    border: none;
    padding: 1rem 2rem;
    background-color: gray;
    cursor: pointer;
    font-weight: bold;
    color: white;
    margin-right: 1rem;
    &.success{
        background-color: #27ae60;
    }
    &.danger{
        background-color: #c0392b;
    }
}

어느정도 줄었고 논리적으로 쉽게 쓸 수 있게 되었다!

Styled Component!

스타일 컴포넌트는 어떨까

npm i –save styled-components

import React, { Component } from 'react';
import styled from 'styled-components';


class App extends Component {
  render(){
    return (
      <Container className="App">
        <Button>Button</Button>
        <Button success>Success</Button>
        <Button danger>Danger</Button>
      </Container>

    );
  }
}
const Container = styled.div`
  height: 100vh;
  width: 100%;
  background-color: #fff;
  padding-top: 10rem;
  text-align: center;
`
const Button = styled.button`
  border: none;
  padding: 1rem 2rem;
  background-color: gray;
  cursor: pointer;
  font-weight: bold;
  color: white;
  margin-right: 1rem;
  &:active,
  &:forcus{
    outline: none;
  }
  background-color: ${props => {
    return props.danger ? "#c0392b" : props.success ? "#27ae60" : "gray";
  } };
`

styled는 기본적으로 컴포넌트이기 때문에 props도 받는다.

장점

  1. 클래스명에대한 고민을 줄일 수 있다. 프로그래머라면 변수명 만드는 것이 제일 고민..
  2. React는 컴포넌트 별로 세분화해서 개발한다. 그렇기 때문에 한두번만 적용해놓으면 편하게 가져다 쓸 수 있다.
  3. extending, props, animation 등 다양한 기능들을 통해서 더 쉽고 빠르게 개발할 수 있다.
  4. SASS나 SCSS를 좋아한다면 별다른 설치없이 바로 사용 가능하다.
  5. React native에서 바로 적용 가능하다! 웹, 앱 동시에 만든다면 너무 좋은 선택

단점

  1. VScode 기준으로 자동완성이 안된다. 끔찍해라 거기다가 읽기도 불편하다. vscode에 좋은 확장프로그램이 있다면 해결
  2. 컴포넌트마다 css가 어디에서 적용되어 있는지 잘모르겠다.
  3. 지금까지 SCSS로 잘 개발하고 있었다면.. 굳이 적용할 이유가 없어보인다.

결론
레이아웃등 글로벌한 CSS는 따로 적용하고 자잘한 네비바, 버튼 등 따로 컴포넌트 적용 해서 사용하면 괜찮을 뜻 하다.

[DEV] CSS FLEXBOX FROGGY 공략!

headerimg
tailwindcss를 통해 한동한 flex에 매력에 푹빠져서 이것 저것 공부하다보니 처음 flex개념을 쉽게 설명해준 사이트가 있어서 다시 공부해본다.!

사실상 게임이기 때문에 공략해본다!

FLEXBOX FROGGY

flex 박스에 있는 개구리를 연꽃위로 이동 시키는 게임이다. 잔말말고 들어가서 게임하자.

flatuicolors.com

img

이제부터 정답만 나열한다.

level 1

justify-content: flex-end;

level 2

justify-content: center;

level 3

justify-content: space-around;

level 4

justify-content: space-between;

level 5

align-items: flex-end;

level 6

justify-content: center;
align-items: center;

level 7

justify-content: space-around; align-items: flex-end;

level 8

flex-direction: row-reverse;

level 9

flex-direction: column;

level 10

flex-direction: row-reverse; justify-content: flex-end;

level 11

flex-direction: column; justify-content: flex-end;

level 12

flex-direction: column-reverse; justify-content: space-between;

level 13

flex-direction: row-reverse; align-items: flex-end; justify-content: center;

level 14

order: 1;

level 15

order: -1;

level 16

align-self: flex-end;

level 17

align-self: flex-end; order: 1;

level 18

flex-wrap: wrap;

level 19

flex-wrap: wrap; flex-direction: column;

level 20

flex-flow: column wrap;

level 21

align-content: flex-start;

level 22

align-content: flex-end;

level 23

flex-direction: column-reverse; align-content: center;

level 24

flex-flow: column-reverse wrap-reverse; align-content: space-between; justify-content: center;

재미있었다.

flex가 3~4가지 속성만 잘 사용하면 컨테이너 정렬은 껌이 될 것이다!

img

[DEV] react native 03 - 완성

headerimg

경고

공부기록용임. 코드나 커리큘럼 방식 등 모든 지적 재산권은 노마드 코더에게 있으며, 무료로 볼 수 있으니 들어가서 여기서 공부할 것!! 갓 니콜라이 노마드 코더님 만세! https://academy.nomadcoders.co

App.js

import Weather from './src/weather/Weather';
import Loading from './src/loading/Loading';

const API_KEY = '받은 api 키를 넣어주세요.';
export default class App extends Component {
  constructor(props) {
    super(props);
    this.state = {isLoading: true};
    if (Platform.OS === 'android' && !Constants.isDevice) {
      // expo에서 gps함수는 안드로이드 에뮬레이터는 돌릴 수 없어 기본 값을 입력해주었다.
      this._getWeather(37.5520514, 126.9885617)
    } else {
      this._getLocationAsync();
    }
  }
  _getLocationAsync = async () => {
    let { status } = await Permissions.askAsync(Permissions.LOCATION);
    if (status !== 'granted') {
      Alert.alert('거절하셨네요', '슬퍼요.');
    }
    //찾기 시작
    try {
      let {
        coords: { latitude, longitude },
      } = await Location.getCurrentPositionAsync({});
      this._getWeather(latitude, longitude)
    } catch (err) {
      Alert.alert('위치를 찾을 수 없어요.', '이상하다?');
    }
  };
  // api를 이용해서 날씨를 가져오는 함수.
  _getWeather = async (latitude, longitude) => {
    const {
      data: {
        main: { temp },
        weather,
        name
      },
    } = await axios.get(
      `http://api.openweathermap.org/data/2.5/weather?lat=${latitude}&lon=${longitude}&appid=${API_KEY}&units=metric`
    );
    this.setState({
      isLoading: false,
      condition: weather[0].main,
      temp: temp,
      name
    });
  };
  render() {
    const { isLoading, condition, temp, name } = this.state;
    return (
      <View style={styles.container}>
        <StatusBar barStyle="dark-content"/>
        { 
          isLoading ? <Loading /> : <Weather temp={Math.round(temp)} condition={condition} name={name}/>
        }
      </View>
    );
  }
}

Weather Component

import React, { Component } from 'react';
import PropTypes from 'prop-types';
import { StyleSheet, View, Text, StatusBar } from 'react-native';
import { MaterialCommunityIcons } from '@expo/vector-icons';
import { LinearGradient } from 'expo-linear-gradient';
import { weatherOptions } from './weatherOptions';

class Weather extends Component{
  render(){
    const PROPS = this.props;
    return (
      <LinearGradient style={styles.container} 
          colors={weatherOptions[PROPS.condition].backgroundColor}>
          <StatusBar barStyle="light-content"/>
          <View style={styles.IconContainer}>
            <MaterialCommunityIcons 
              size={96} 
              name={weatherOptions[PROPS.condition].iconName} color="white"
            />
            <Text style={styles.temp}>{PROPS.temp}°</Text>
          </View>
          <View style={styles.textContainer}>
            <Text style={[styles.text, styles.city]}>{PROPS.name}</Text>
            <Text style={[styles.text, styles.title]}>
              <Text>{weatherOptions[PROPS.condition].kr}</Text>
              <Text style={[fontSize:22]}>  {PROPS.condition}</Text>
            </Text>
            <Text style={[styles.text, styles.subtitle]}>{weatherOptions[PROPS.condition].subTitle}</Text>
          </View>
      </LinearGradient>
    )
  }
}

Weather.PropTypes = {
  temp: PropTypes.number.isRequired,
  name: PropTypes.string.isRequired,
  condition: PropTypes.oneOf([
    'Thunderstorm',
    'Drizzle',
    'Rain',
    'Snow',
    'Atmosphere',
    'Clear',
    'Clouds',
    'Haze',
    'Mist',
    'Smoke',
    'Haze',
    'Dust',
    'Fog',
    'Sand',
    'Dust',
    'Ash',
    'Squall',
    'Tornado'
  ]).isRequired,
};

const styles = StyleSheet.create({
  container: {
    flex: 1,
    justifyContent: 'center',
    alignItems: 'center',
  },
  IconContainer: {
    justifyContent: 'center',
    alignItems: 'center',
    flex: 1,
  },
  textContainer: {
    justifyContent: 'center',
    alignItems: 'flex-start',
    flex: 1,
    paddingHorizontal: '15%',
    width: '100%'
  },
  text: {
    color: 'white',
  },
  city: {
    fontSize: 22,
  },
  title: {
    fontSize: 32
  },
  subtitle: {
    fontSize: 16
  },
  temp: {
    fontSize: 42,
    paddingLeft: 10,
    color: 'white',
  },
});

export default Weather;

weatherOptions.js는 이렇게 생겼다. image

완성

image
리액트 네이티브로 만든 첫 앱!

리액트는 배우면 배울수록 재미있는 것 같다.
물론 angular로는 대형 홈페이지 밖에 안만들었으니 어렵고 짜증날 수 밖에 없지만 많은 불편 사항이 있었다.
다음엔 간단한 프로젝트 후에 평소 생각에만 있던 앱을 만들어볼 계획이다.

[DEV] react native 02 - component와 layout

headerimg

경고

공부기록용임. 코드나 커리큘럼 방식 등 모든 지적 재산권은 노마드 코더에게 있으며, 무료로 볼 수 있으니 들어가서 여기서 공부할 것!! 갓 니콜라이 노마드 코더님 만세! https://academy.nomadcoders.co

App을 만드는 3가지 방식

  1. 네이티브 방식 Swift Objective-c, java 등으로 ios, android를 각각 만드는 방법
  2. 하이브리드 웹뷰를 이용해 cordova, phoneGap 을 이용해 하이브리드 방식으로 심플한 앱을 제작

    Ionic도 결국 웹뷰..쪽 아닌가 싶다

  3. react native javascript를 android나 ios가 이해할 수 있게 하는 브릿지가 있다.
    데이터량이 많아져 브릿지가 트레픽잼이 걸리면 점차 느려질 수 있다. 거기다가 뷰가 많아지면 더 느려짐..
    적절한 라이프사이클 관리가 필수적임.

Component

export default function App() {
  return (
    <View style={styles.container}>
      <Text>Title~~</Text>
    </View>
  );
}
// View는 일단 div이고 Text는 span으로 생각하자.
// 스타일은 style={styles.container} 이런식으로 넣어주고
const styles = StyleSheet.create({
  container: {
    flex: 1,
    backgroundColor: '#ddd',
    alignItems: 'center',
    justifyContent: 'center',
  },
}); // 여기서 정의한다.

Layout

export default function App() {
  return (
    <View style={styles.container}>
      <View style={styles.yellow}></View>
      <View style={styles.blue}></View>
    </View>
  );
}

const styles = StyleSheet.create({
  container: {
    flex: 1
  },
  yellow:{
    flex: 2,
    backgroundColor: 'yellow'
  },
  blue:{
    flex: 1,
    backgroundColor: 'blue'
  }
});

이러면 어떻게 될까 reat-native에서는 flex가 웹에서는 row인 것에 반해 기본적으로 column이다. 거기에 flex값은 일종의 내가 차지할 크기 비율을 따진다. 만약 전체 넓이를 3으로 쳤을때, yellow는 2만큼, blue는 1만큼을 가지게 된다. container는 혼자있기 때문에 1은 100%를 나타낸다.

image

웹과 다르게 폰은 가로 세로 길이가 항상 변하고 수많은 기기들의 사이즈가 모두다 다르기 때문에 절대 width나 height를 layout에서는 최대한 쓰지 않게 해야한다. 모두 FLEX 하자

[DEV] react native 01 - expo와 안드로이드

headerimg

경고

공부기록용임. 코드나 커리큘럼 방식 등 모든 지적 재산권은 노마드 코더에게 있으며, 무료로 볼 수 있으니 들어가서 여기서 공부할 것!! 갓 니콜라이 노마드 코더님 만세! https://academy.nomadcoders.co

시작하기전

나는 니콜라스때문이 아닌 이미 expo를 쓰기로 마음먹은 상태였다.
expo는 생태계가 기본 react-native보다 좁고 빌드파일이 크며, 다양한 기능을 만들어 쓰기 힘들 수 있다.
그러나 초기 공수가 적게 들어가며, 학습용도로써 매우 좋아보여 일단 선택하게되었다.
애초에 지금 개발하고 싶은 앱도 네이티브 기능을 쓰지 않으니 뭐.. 적당하다 싶다.

install

  1. npm install expo-cli –global

  2. expo.io 접속 & 가입
  3. 프로젝트 생성

    expo init my-new-project
    cd my-new-project
    expo login
    expo start

  4. [옵션] 깃헙 연결하기

끗!

실행

에뮬레이터

  1. 안드로이드 기준 android studio 설치
  2. 에뮬레이터 설치
    image

    AVD Manager 들어가서 아무폰이나 설치, 아니면 구글링해서 새로운 폰 만들어도됨

  3. 다시 AVD Manager와서 초록 화살표로 실행
    image

  4. expo dev 창에서 에뮬레이터 실행
    image

내 폰

  1. 폰에서 expo 설치 후 expo dev 창의 QR코드를 인식 시키면 바로 실행!

[DEV] 리액트 06 - Routing!

headerimg

경고

공부기록용임. 코드나 커리큘럼 방식 등 모든 지적 재산권은 노마드 코더에게 있으며, 무료로 볼 수 있으니 들어가서 여기서 공부할 것!! 갓 니콜라이 노마드 코더님 만세! https://academy.nomadcoders.co

Router

리액트로 라우팅 기능 만들기

npm i react-router-dom –save

image

폴더구조를 바꿔주고 App.js에 있던 movie list는 home으로 넘겨주었다. 그리고 App.js에 라우터를 달아줄 것이다.

function App(){
  return (
    <BrowserRouter>
      <Navigation></Navigation> //Navigation Component
      <Route path="/" exact={true} component={Home}/>
      // 정확하게 맞을때만 연결해준다.
      <Route path="/about" component={About}/>
    </BrowserRouter>
  )
}

// Navigation
function Navigation() {
  return (
    <div>
      <Link to="/">Home</Link>
      <Link to="/about">About</Link>
    </div>
  );
}

갓콜라스는 hashRouter를 썼다. /#/ 못생긴 해쉬가 붙어있고 SEO에서도 불리하다는 소리까지!! 거기다가 레거시 브라우저만 지원하고 location.key 같은건 작동하지 않는단다.. 장점은 깃페이지에 올릴땐 설정하기 쉽다? 라고함.

일단은 페이지 이동은 이렇게한다. 공식 문서를 읽어보면 props도 간편하게 object로 보낼 수 있다.

다음은 무비디테일?

방식은 1가지이다.

  1. 리스트에서 영화를 클릭 시 movie-detail 에 들어가게 하고 props로 데이터를 다 던져준다.
  2. 리스트에서 영화를 클릭 시 영화의 id or key를 줘서

1. props로 다던져준다

// Movie Component 에서 Link를 클릭 하면 다던져주고
class Detail extends React.Component {
  constructor(props) {
    super(props);
    const { location, history } = this.props;
    if (location.state === undefined) {
      history.push('/');
    }
    this.state = {
      infomation: this.props.location.state,
    };
  }
  render() {
    const info = this.state.infomation;
    return <span>
      {info.title}
    </span>;
  }
}

이 방법은 URL로 접근 할 수 없기 때문에 무조건 클릭으로 접속해야만 한다는 것!

2. ID만 받는다 /movie/:id에서 id를 받기 위해선 react router domuseParams()를 써야한다. Hook이기 때문에 아래 규칙을 지켜주자.

image

import React, { useState, useEffect } from "react";
import axios from 'axios';
import { useParams } from "react-router-dom";

function Detail(){
  const [data, setData] = useState({});
  const apiUrl = 'https://yts-proxy.now.sh/movie_details.json?movie_id=';
  let {id} = useParams();

  useEffect(() => {
    async function getMovie(id){
      const {data:{data:{movie}}} = await axios.get(apiUrl + id);
      setData(movie);
    };
    getMovie(id);
  },[]);

  return (
    <span>{data.title}</span>
  )
}
export default Detail;

Hook을 이용하는 방법! 물론 useParams없이 다른 쿼리 해석 방식을 쓰면 class에서도 가능함. function component에서 axios나 여타 life cycle없이 사용하는 방법이다.

마무리

원래라면 redux나 mobx를 이용해서 한번 로딩한 list는 로딩을 안한다든지, list에 page나 limit api를 이용해서 무한 스크롤링 등 더 많이 추가해볼 사항이 있지만 다른 프로젝트를 하기위해! 여기서 마무리하고 다음번엔 더 큰 프로젝트를 해봐야겠다

[DEV] 리액트 05 - Axios로 영화 뿌리기

headerimg

경고

공부기록용임. 코드나 커리큘럼 방식 등 모든 지적 재산권은 노마드 코더에게 있으며, 무료로 볼 수 있으니 들어가서 여기서 공부할 것!! 갓 니콜라이 노마드 코더님 만세! https://academy.nomadcoders.co

드디어 무비앱을 만드는구나 행볶

Fetching Movies

api를 받아오는 툴은 axios를 사용한단다. 니꼴라스왈 axios는 땅콩을 감싼 멋진 초콜릿이야. axios는 기본적으로 http요청을 하는 통신 모듈이다. npm으로 설치 가능!

npm i axios

무료 api는 yts에서 가져올 수 있다. yts는 불법 토렌트 사이트인데..

거기다가 url이 자주 바뀐다고 한다. 그러니 갓니꼴라스가 만든 갓니꼴라스 깃허브 여기서 proxy api를 가져올 수 도 있다.

https://yts-proxy.now.sh/list_movies.json

class App extends React.Component{
  constructor(props){
    super(props)
    this.state = {
      apiUrl: 'https://yts-proxy.now.sh/list_movies.json?sort_by=rating',
      // sort_by=rating을 추가함.
      isLoading: true,
      movies: []
    }
  }

  // js에게 async와 await는 getMovies function은 조금 시작이 필요하고 우리는 기다려야한다 라는 뜻이다.
  getMovies = async () => {
    const {data:{data:{movies}}} = await axios.get(this.state.apiUrl);
    this.setState({ movies, isLoading: false });
  }
  componentDidMount(){
    this.getMovies();
  }
  render(){
    const { isLoading } = this.state;
    return (
      <div>
        {isLoading ? "Loading..." : this.renderMovie()};
      </div>
    )
  }
  // 로딩이 다되면 Movie Component를 호출함.
  renderMovie(){
    return (
      this.state.movies.map(movie=>{
        return (
          <Movie
            key={movie.id}
            id={movie.id}
            year={movie.year}
            title={movie.title}
            summary={movie.summary}
            poster={movie.medium_cover_image}
          />
        );
      })
    )
  }
}

// Movie Component
function Movie({ id, year, title, summary, poster }) {
  return <h1>{title}</h1>;
}

Movie.prototype = {
  id: PropTypes.number.isRequired,
  year: PropTypes.number.isRequired,
  title: PropTypes.string.isRequired,
  summary: PropTypes.string.isRequired,
  poster: PropTypes.string.isRequired
};

자 그리고 커스텀좀 해볼까 SASS추가하고

npm install node-sass –save 파일좀 만들고 import 시켜서 적용하면 끝.

image

이것 저것 만들고 싶어서 일단 이렇게 만들어 봄. 갓니꼬는 다른 스타일을 하니 확인해볼 것.

Pagination


© 2018. All rights reserved.