React 정리 #4



React 정리 #4


실습 #1


  • props로 기본 필드, state 필드, 함수 등을 받아올 수 있고 보낼 수 있다.
import React, { Component } from 'react'
import Sample from './190808_sample'

export default class App extends Component {
  state = {
    animal_ar : ['호랑이', '코끼리', '토끼'],
  }

  render() {
    return (
      <div>
        <ol>{
            this.state.animal_ar.map((v, k) => {
              return <li>{v}</li>
            })
          }
        </ol>
        <button onClick={() => {
          this.setState({
            animal_ar: this.state.animal_ar.concat('독수리')
          })
        }}>독수리 버튼</button>
      </div>
    )
  }
}



실습 #1


import React, { Component } from 'react'
import Bpp from './bpp'

export default class App extends Component {
  
  state = {
    animal : ['호랑이', '코끼리', '앵무새'],
  }

  animalEvent = () => {
    let num = Math.floor(Math.random() * 3)

    this.setState({
      animal_name : this.state.animal[num],
    })
  }`

  render() {
    return (
      <div>
        <h1>{this.animal_name}</h1>
        <Bpp animalEvent = {this.animalEvent}/>
      </div>
    )
  }
}


실습 #1


  • 알림창
import React, { Component } from 'react'

export default class App extends Component {
  
  // 알림창 띄우는 3개
  f1 = () => {
    // 알림창
    alert("안녕하세요")
  }
  f2 = () => {
    // 입력가능한 알림창
    // 입력 결과값이 리턴된다. (취소시 null)
    let result = prompt("안녕하세요", "입력하세요")
    console.log(result);
  }
  f3 = () => {
    // 확인,취소 알림창
    // 입력 결과값이 리턴된다. (확인 true, 취소 false)
    let result = window.confirm("정말 삭제하시겠습니까?")
    console.log(result);
  }

  f4 = (e) => {
    console.log("입력");
    console.log(e.target.value);
  }

  f5 = (e) => {
    this.setState({
      txt : e.target.value
    })
  }

  state = {
    txt: "내용",
    text: ""
  }

  render() {
    return (
      <div>
        <button onClick = {this.f1}>f1</button>
        <button onClick = {this.f2}>f2</button>
        <button onClick = {this.f3}>f3</button>
        {/* 익명함수를 통하여 alert 호출 */}
        <button onClick = {() => {alert("글쎄요..")}}>글쎄요 버튼</button>
        <input
        //객체의 속성이기 때문에 콤마(,)를 사용하지않음.
          type = {Text}
          name = "메세지"
          placeholder = "값을 입력하세요!"
          onChange = {this.f5}
        // input 태그는 한줄로 죽 안쓰기 때문에 엔터
        />
        <button onClick = {() => {alert(this.state.txt)}}>알람</button>
      </div>
    )
  }
}

import React, { Component } from 'react'
import Sample from './190808_sample'

export default class App extends Component {
  state = {
    animal_ar : ['호랑이', '코끼리', '토끼'],
  }

  render() {
    return (
      <div>
        <ol>{
            this.state.animal_ar.map((v, k) => 
            {
              return <li onClick = {() => {
                this.setState({
                  animal_ar: this.state.animal_ar.slice(0, k).concat(this.state.animal_ar.slice(k + 1, this.state.animal_ar.length))
                })
              }}
               key = {k}>{v}</li>
            })
          }
        </ol>

        <button onClick={() => {
          this.setState({
            animal_ar: this.state.animal_ar.concat('독수리'),
          })
        }}>PUSH</button>

        <button onClick={() => {
          // state 안에 들어가 있을 경우 pop을 사용할 수 없으니 slice로 잘라서 원 배열에 마지막 요소만을 빼고 잘라버린다.
          this.setState({
            animal_ar: this.state.animal_ar.slice(0, this.state.animal_ar.length - 1)
          })
        }}>POP</button>
      </div>
    )
  }
}
import React, { Component } from 'react'
import Sample from './190808_sample'

export default class App extends Component {
  state = {
    animal_ar : ['호랑이', '코끼리', '토끼'],
  }

  render() {
    return (
      <div>
        <ol>{
            this.state.animal_ar.map((v, k) => 
            {
              return <li onDoubleClick = {() => {
                this.setState({
                  animal_ar: this.state.animal_ar.slice(0, k).concat(this.state.animal_ar.slice(k + 1, this.state.animal_ar.length))
                })
              }}
               key = {k}>{v}</li>
            })
          }
        </ol>

        <button onClick={() => {
          this.setState({
            animal_ar: this.state.animal_ar.concat('독수리'),
          })
        }}>PUSH</button>

        <button onClick={() => {
          // state 안에 들어가 있을 경우 pop을 사용할 수 없으니 slice로 잘라서 원 배열에 마지막 요소만을 빼고 잘라버린다.
          this.setState({
            animal_ar: this.state.animal_ar.slice(0, this.state.animal_ar.length - 1)
          })
        }}>POP</button>
      </div>
    )
  }
}
<ol>{
            this.state.animal_ar.map((v, k) => 
            {
              return <li onDoubleClick = {() => {
                let arr = [
                  ...this.state.animal_ar.slice(0, k), 
                  ...this.state.animal_ar.slice(k + 1, this.state.animal_ar.length)
                ]

                this.setState({
                  animal_ar: arr
                })
              }}
               key = {k}>{v}</li>
            })
          }
        </ol>
import React, { Component } from 'react'
import Sample from './190808_sample'

export default class App extends Component {
  state = {
    ar : ['호랑이', '코끼리', '토끼'],
  }

  render() {
    //* this.state.ar을 'ar'로 치환
    // const ar = this.state.ar

    //* 비구조화 할당을 사용
    const {ar} = this.state

    //TODO 위 두 예문은 같은 기능을 함
    
    return (
      <div>
        <ol>{
            ar.map((v, k) => 
            {
              return <li onDoubleClick = {() => {
                // 전개연산자로 붙임
                let arr = [
                  ...ar.slice(0, k), 
                  ...ar.slice(k + 1, ar.length)
                ]

                this.setState({
                  animal_ar: arr
                })
              }}
               key = {k}>{v}</li>
            })
          }
        </ol>

        <button onClick={() => {
          this.setState({
            animal_ar: ar.concat('독수리'),
          })
        }}>PUSH</button>

        <button onClick={() => {
          // state 안에 들어가 있을 경우 pop을 사용할 수 없으니 slice로 잘라서 원 배열에 마지막 요소만을 빼고 잘라버린다.
          this.setState({
            animal_ar: ar.slice(0, ar.length - 1)
          })
        }}>POP</button>
      </div>
    )
  }
}
import React, { Component } from 'react'
import Sample from './190808_sample'

export default class App extends Component {
  render() {
    return (
      <div>
        <Bpp a = '호랑이' b = {10}/>
      </div>
    )
  }
}

// 함수형 컴포넌트 예제
// Bpp = (props)로 받아서 this.props로 받을 필요 없이, 안에 {a, b}를 넣어서 바로  a, b로 사용함.
const Bpp = ({a, b}) => {
  return (
    <div>
      <h1>Bpp</h1>
      <h2>{a}</h2>
      <h2>{b}</h2>

    </div>
  );


실습 #2


  • Props와 State의 차이점
  • 크게 값을 갱신할수 있냐, 없냐로 구분한다.
    • Props
      • 값을 단순히 받아오고, 값 갱신이 불가능.
    • State
      • 컴포넌트 자체에서 초기화 하며, 값 갱신이 가능하다.
        • 단독으로 값 갱신은 불가능 하며, 함수를 사용해아하는데 setState() 라는 함수를 사용한다
  • 꼭 State를 사용해야 하는 이유가 있는가?
    • 일반 필드명으로도 선언이 가능하고, 값도 갱신이 가능하다. 하지만…
    • setState로 값 갱신시 render()함수가 호출되어 화면상에 즉각적으로 렌더링이 가능하다. 하지만 일반 필드명으로 값을 갱신시, render()함수를 가지고 오지 않아, 즉각적으로 렌더링이 되지 않고 ‘값’만 변경된다.
    • setState
  • SetState는 비동기 함수이다
    • 대신 다음 render() 전까지는 갱신이 된다는것을 보장한다.
    • (ex) setState 안에서 갱신시킨 n1을 console.log()로 출력할 경우 값이 갱신되지 않은 상태로 보임
  • 정리
    1. 컨트롤 안에 값이 갱신되는 함수(화면에 보여야 하는 데이터)는 모두 state를 사용하자
    2. 화면에 보이는것과 관계없이 컴포넌트와 관계없이 내부적으로만 사용하는 변수는 필드로 사용해도 무방
import React, { Component } from 'react';

class EventPractice extends Component {

  state = {
    username: '',
    email: '',
    message: ''
  }

  handleChange = (e) => {
    this.setState({
      [e.target.name]: e.target.value
    });
  }

  handleClick = () => {
    alert(this.state.username + ': ' + this.state.message);
    this.setState({
      username: '',
      message: ''
    });
  }

  handleKeyPress = (e) => {
    if (e.key === 'Enter') {
      this.handleClick();
    }
  }


  render() {
    return (
      <div>
        <h1>이벤트 연습</h1>
        <input 
          type="text"
          name="username"
          placeholder="유저명"
          value={this.state.username}
          onChange={this.handleChange}
        />
        <input 
          type="text"
          name="message"
          placeholder="아무거나 입력해보세요"
          value={this.state.message}
          onChange={this.handleChange}
          onKeyPress={this.handleKeyPress}
        />
        <button onClick={this.handleClick}>확인</button>
      </div>
    );
  }
}

export default EventPractice;



예시 #3-1


let n = 'a'

let obj = {
    [n]: 0,  // []이걸 a라고해줌
    b: 10,
    c: 20,
}

console.log(obj);


실습 #4-1


let ar = [10, 20, 30, 40, 50]
console.log(ar);

// map을 사용해 가공된 데이터 저장이 가능하다.
let br = ar.map((n) => { 
    console.log(n) 
    return n * 10
})

// value값과 함께 key값도 받아올 수 있다.
let cr = ar.map((n, key) => { 
    console.log(n, key) 
    return n * 10
})

console.log(br);

import React, { Component } from 'react'

export default class App extends Component {
  
  // 알림창 띄우는 3개
  f1 = () => {
    // 알림창
    alert("안녕하세요")
  }
  f2 = () => {
    // 입력가능한 알림창
    // 입력 결과값이 리턴된다. (취소시 null)
    let result = prompt("안녕하세요", "입력하세요")
    console.log(result);
  }
  f3 = () => {
    // 확인,취소 알림창
    // 입력 결과값이 리턴된다. (확인 true, 취소 false)
    let result = window.confirm("정말 삭제하시겠습니까?")
    console.log(result);
  }

  f4 = (e) => {
    console.log("입력");
    console.log(e.target.value);
  }

  f5 = (e) => {
    this.setState({
      txt : e.target.value
    })
  }

  state = {
    txt: "",
  }

  render() {
    // 요사이는 this 필요없음
    let ar = ['호랑이', '코끼리', '독수리']
    let br = ar.map((v, k) => {
      console.log(v, k);
      // version이 업데이트되어서 key값을 매핑해야함. 안그럼 오류.
      return <li key={k}>{v}</li>
    })

    return (
      <div>
        <button onClick = {this.f1}>f1</button>
        <button onClick = {this.f2}>f2</button>
        <button onClick = {this.f3}>f3</button>
        {/* 익명함수를 통하여 alert 호출 */}
        <button onClick = {() => {alert("글쎄요..")}}>글쎄요 버튼</button>
        <input
        //객체의 속성이기 때문에 콤마(,)를 사용하지않음.
          type = "Text"
          name = "메세지"
          placeholder = "값을 입력하세요!"
          onChange = {this.f5}
        // input 태그는 한줄로 죽 안쓰기 때문에 엔터
        />
        <button onClick = {() => {alert(this.state.txt)}}>알람</button>

      {br}

      </div>
      
    )

    
  }
}
render() {
    // 요사이는 this 필요없음
    let ar = ['호랑이', '코끼리', '독수리']
    let br = ar.map((v, k) => <li key={k}>{v}</li>)
// rcfc로 생성
import React, { Component } from 'react';

class App extends Component {

  // Mount = 보조시스템을 꼽을때 사용 <=> Unmount

  // render()되기 전에 값 갱신이 필요할때 사용
  // 'will'은 어떤 작업을 하기 전에 일어남
  componentWillMount() {
    console.log(1);
  }

  // render() 된 후에 값 갱신이 필요할때 사용
  // 'did'는 어떤 작업을 한 후에 일어남
  componentDidMount() {
    console.log(2);
  }

  componentWillReceiveProps(nextProps) {
    console.log(3);
  }

  shouldComponentUpdate(nextProps, nextState) {
    console.log(4);

  }

  componentWillUpdate(nextProps, nextState) {
    console.log(5);

  }

  componentDidUpdate(prevProps, prevState) {
    console.log(6);

  }

  componentWillUnmount() {
    console.log(7);

  }

  render() {
    console.log(8);
    // 컴포넌트의 lifecycle
    // 실행시 1, 8, 2가 나옴.
    // 나머지 함수는 props로 넘어갈때 , 넘어가고나서 등의 상황에 사용
    return (
      <div>

      </div>
    );
  }
}

App.propTypes = {

};

export default App;
import React, { Component } from 'react'

export default class App extends Component {
  render() {
    return (
      <div>
        <Bpp a='호랑이'/>
      </div>
    )
  }
}

// 'state'를 사용할 일이 없다. => 함수형 컴포넌트
// 앞에 나왔던 7가지의 life cycle이 없어서 가볍다. => 함수형 컴포넌트
// 부모에게 props 받는건 가능 => 함수형 컴포넌트

// 2. 함수형 컴포넌트이며, rsc 단축키로 생성한다.
const Bpp = (t) => {
  return (
    <div>
      <h1>Bpp</h1>
      {t.a}
    </div>
  );
};

// 1. 함수형 컴포넌트
// function Com () {
//     return (
//       <div>
//         <h1>COM</h1>
//         <h1>{this.props.a}</h1>
//       </div>
//     )
// }


정리


  • props와 state는 값의 갱신 가능 유무에 따라 갈린다.
  • state와 일반 필드의 차이는 render() 함수를 불러오느냐에 따라 구분한다.
  • import* as...를 사용하면 Component내의 function들만 불러온다.
  • import ...를 사용하면 default Component를 불러온다.
  • import ..., {...}를 사용하면 default Component를 포함해 {}안에 들어있는 Component도 함께 불러온다.
  • 내부에서만이 아닌 외부에서도 함수나 컴포넌트를 사용하려면 앞에 export를 붙여 주어야 한다.

import React, { Component } from 'react'
import Sample from './190808_sample'
import { connect } from 'react-redux'

class App extends Component {
  render() {
    console.log(App);
    return (
      <div>
        {/* <Bpp a = '호랑이' b = {10}/> */}
        <h1>{this.props.num}</h1>
        <h1>{this.props.age}</h1>
        <button onClick = {this.props.onAgeClick}>에러 생성기</button>
      </div>
    )
  }
}

//! Action
// 내가 버튼을 onClick을 사용하지 않고, onmyclick을 쓰겠다. 라고 정의를 하는것이 action이다.
// 액션이 실행되고 데이터
//! java에서의 이벤트와 동격이다.

// dispatch는 내장 함수임.
// 객체를 인자로 받음.
// dispatch type은 해당 Key값을 모두 대문자로 해서 넣는것이 일반적임.
// action에서 원하는 기능을 찾아갈 때 type을 통해 찾아간다.
// Action을 걸 떄 onMyClick으로 잡는부분을 설정하는 곳.
export const mapActionToProps = (dispatch) => {
  console.log('Action');
  return {
    // 카멜 표기법
    onMyClick: () => {
      dispatch({
        type: 'MYCLICK'
      })
    },
    onAgeClick: () => {
      dispatch({
        type: 'AGECLICK'
      })
    }
  }
}

// reduse는 람다로 안씀
// 주는놈은 프로듀서,받는쪽 리듀스. (hadoop에서 사용)
// state의 초기값을 reduce를 처음 실행했을때 설정을 해주어야 한다. - 현재 10으로 설정하였음.
export function reduce(state = {num: 10, age: 100}, action) {
  // 매개변수에서 state를 받을때 사용할 변수의 초기값을 설정해주어야한다.
  // reduce => setState 함수 코드와 같은 역할을 한다.
  console.log('Reduce');
  switch (action.type) {
    //* 1. state의 모든 상태변화는 reduce에서 실행된다. (setState를 이용한 모든 갱신은 모두 여기서 일어난다.)
    //* 2. reduce 함수는 반드시 순수함수여야 한다.
    //* - 순수함수란? 함수로 전달된 인수 값을 변경시키지 않고 외부의 전역변수를 끌고와서 사용하지 않는 함수

    //TODO =====================
    case 'MYCLICK': 
    state = {
      num: state.num + 1,
    }
    console.log(state.num);
    console.log(action.type);

    // 실질적으로 이 return문에서 setState가 일어난다. store에서 값이 변경되었다는걸 알리고 state가 해당 값을 받아온다.
    case 'AGECLICK':
    state = {
      ...state,
      age: state.age + 1,
    }

    return state 
    //TODO =====================
    // default 에서는 반드시 state를 걸어줘야한다.
    default:
      return state
  }
}

// state가 지나면 컴포넌트로 돌아옴
// state의 값은 store에서 가져왔다. 라고 생각해도 무방.
const mapStateToProps = (state) => {
  console.log('state');
  return {
    // 여기서 데이터 갱신(num = state.num + 1)을 하려하지마라. 데이터 갱신은 무조건 reduce에서. 
    // store에서 갱신시키고 싶은것은 reduce에서 해라. 여기는 store를 갱신시키는게 아니다.
    // 데이터를 최종 가공하는 용도로 사용이 된다.
    //* 실제 달러 <=> 원화 환산으로 사용하기가 좋다.
    //* 실제 값은 `12`달러지만 *1000을 해주면 달러로 변환이 되어 `12000`원이 되듯이 나온다.
    num: state.num,
    age: state.age
  }
}

// 함수형 컴포넌트 예제
// Bpp = (props)로 받아서 this.props로 받을 필요 없이, 안에 {a, b}를 넣어서 바로  a, b로 사용함.
const Bpp = ({a, b}) => {
  return (
    <div>
      <h1>Bpp</h1>
      <h2>{a}</h2>
      <h2>{b}</h2>
    </div>
  );
};

const Cpp = ({a, b}) => {
  return (
    <div>
      <h1>Bpp</h1>
      <h2>{a}</h2>
      <h2>{b}</h2>
    </div>
  );
};

export default connect(
  mapStateToProps, mapActionToProps, 
) (App);
import React, { Component } from 'react'
import { connect } from 'react-redux'

class App extends Component {
  render() {
    return (
      <div>
        <h1>{this.props.num}</h1>
        <button onClick = {this.props.onAddClick}>증가 버튼</button>
        <Dec />
      </div>
    )
  }
}

//* Step 1
export const mapActionToProps = (dispatch) => {
  console.log('Action');
  return {
    // 카멜 표기법
    onAddClick: () => {
      dispatch({
        type: 'ADDCLICK'
      })
    },
    onDecClick: () => {
      dispatch({
        type: 'DECCLICK'
      })
    }
    
  }
}

//* Step 3
export function reduce(state = {num: 0}, action) {
  console.log('Reduce');
  switch (action.type) {

    //TODO =====================
    case 'ADDCLICK': 
    state = {
      num: state.num + 1
    }
    console.log(state.num);
    return state

    case 'DECCLICK': 
    state = {
      num: state.num - 1
    }
    console.log(state.num);
    return state 
    //TODO =====================
    default:
      return state
  }
}

//* Step 2
const mapStateToProps = (state) => {
  console.log('state');
  return {
    num: state.num,
  }
}

class Bpp extends Component {
  render() {
    return (
      <div>
        {/* Step 5 */}
        <button onClick = {this.props.onDecClick}>감소 버튼</button>
      </div>
    );
  }
}

//? 현재 컴포넌트에서 사용하는 일반적인 방법
export default connect(
  mapStateToProps, mapActionToProps, 
) (App);

//! 다른 컴포넌트에서 태그모양으로 받기 위해 정의
const Dec = connect(mapStateToProps, mapActionToProps,) (Bpp);
import React, { Component } from 'react'
import { connect } from 'react-redux'

class App extends Component {
  render() {
    return (
      <div>
        <h1>{this.props.num}</h1>
        <button onClick = {this.props.onAddClick}>증가 버튼</button>
        <Bpp />
      </div>
    )
  }
}

//* Step 1
export const mapActionToProps = (dispatch) => {
  return {
    // 카멜 표기법
    onAddClick: () => {
      dispatch({
        type: 'ADDCLICK'
      })
    },
    onDecClick: () => {
      dispatch({
        type: 'DECCLICK'
      })
    }
  }
}

//* Step 3
export function reduce(state = {num: 0}, action) {
  switch (action.type) {

    //TODO =====================
    case 'ADDCLICK': 
    state = {
      num: state.num + 1
    }
    return state

    case 'DECCLICK':
      state = {
        num: state.num - 1
    }
    return state
    
    //TODO =====================
    default:
      return state
  }
}

//* Step 2
const mapStateToProps = (state) => {
  return {
    num: state.num,
  }
}

class Bpp extends Component {
  render() {
    return (
      <div>
        <Ctx />
      </div>
    );
  }
}

class Cpp extends Component {
  render() {
    return (
      <div>
        <button onClick = {this.props.onDecClick}>감소 버튼</button>
      </div>
    );
  }
}

//? 현재 컴포넌트에서 사용하는 일반적인 방법
export default connect(
  mapStateToProps, mapActionToProps, 
) (App);

//! 다른 컴포넌트에서 태그모양으로 받기 위해 정의
const Ctx = connect(mapStateToProps, mapActionToProps,) (Cpp);
import React, { Component } from 'react'
import { connect } from 'react-redux'

class Bpp extends Component {
  render() {
    return (
      <div>
        {/* //* Step 1 */}
        <Ctn />
      </div>
    )
  }
}

//* Step 2
//! redux : Action
export const mapActionToProps = (dispatch) => {
  return {
    // 카멜 표기법
    onMyClick: () => {
      dispatch({
        type: 'MYCLICK'
      })
    },
  }
}

//* Step 4는 reduce를 store에 등록하는것임. 지금은 등록되어있어 패스.

//* Step 3
//! redux : reduce
export function reducer(state = null, action, e) {
  switch (action.type) {
    case 'MYCLICK' :
        console.log('in MyClick');
    // return값에 state가 없으니 null로 사용해도 무방하다.
    return state
  
    default:
      return state
  }
}

const mapStateToProps = (state) => {
  return {
  }
}

class Com1 extends Component {
  render() {
    return (
      <div>
        {/* //* Step 1 */}
        <button onClick = {this.props.onMyClick}>안녕 버튼</button>
      </div>
    );
  }
}

//! 3가지를 모두 묶은것을 container라고 한다.
//* Ctn은 이제 태그처럼 사용된다. (첫글자는 대문자여야함)
const Ctn = connect(null, mapActionToProps,) (Com1);

export default Bpp;



© 2019. by mintheon

Powered by mintheon