Archive

[REACT] State / Event

manon_e 2021. 9. 4. 19:33
반응형

 

 

 

 

 

 

State ?

 

 

 

🔻 State란

: 컴포넌트 내부에서 가지고있는, 객체형태의 컴포넌트의 상태값이며 

함수내에 선언된 변수처럼 컴포넌트 내에서 정의하고  사용하며 변경까지시킬 수 있는 객체.

(state는 object이고 compo의 data를 넣을 공간이 있고, 이 데이터는 변함)

 

 

- State가 필요한 이유 

   : 컴포넌트안의 요소에서 그 상태값반영해서 데이터가 바뀔때마다 효율적으로 화면(UI)에 나타내기 위해서 필요.

 

 

- State와 Props의 차이

   : 두객체 모두 렌더링 결과물에 영향을 주는 정보(컴포넌트의 속성값)를 가짐.

    props :  (함수의 매개변수처럼) 부모로부터 props를 받고,

                    이 props는 상속받은 컴포넌트 내에서 수정 불가능(읽기전용)

    state : (함수내에 선언된 변수처럼) 컴포넌트의 내부에서 선언되기 대문에 변할수있고 직접변경가능

                 또한, state를 통해 props데이터를 참조시켜 데이터를 내부에서 은닉하는 즉, 캡슐화통해 코드의 사용성 만듬

 

 

- 클래스형 컴포넌트에서 State를 정의하는 방법

   : constructor함수를 component선언문과 render함수 사이에 작성하여

     dot notations(this.state.~)을 사용하여 객체의 특성에 접근하여 그 값을 지정

import React from 'react';

class State extends React.Component {
  constructor() {          //함수
    super();               //super를 호출
    this.state = {         //state 객체
      color: 'red'          //dolor의 key값으로 'red' value지정
    };
  }

  render() {              //화면에 나타내고 싶은 JSX요소
    return (
      <div>
        <h1>Class Component | State</h1>
      </div>
    );
  }
}

export default State;

ex) 글자색

this(해당컴포넌트) .state (의 state객체) .color (의 key=color값=red)

더보기
import React, { Component } from 'react';

class State extends Component {
  constructor() {
    super();
    this.state = {
      color: 'red',
      abc: '40px'
    };
  }

  render() {
    return (
      <div>
        <h1 style={{ color: this.state.color, fontSize: this.state.abc }}>
        Class Component | State
        </h1>
      </div>
    );
  }
}

export default State;

https://lucybain.com/blog/2016/react-state-vs-pros/

 

Lucy Bain

 

lucybain.com

 

 

 

 

 


state 변경

 

 

 

> 부모의 state를 props로 전달가능

> 자신의 state값 바꾸려면 this.setState로 변경

> event handler함수 

  자식 compo에서 부모 compo의 state변경하려면 this.setState 로직담긴 함수를 props로 받아야함

 

 

 

ex) 버튼클릭 event

 

import React, { Component } from 'react';

class State extends Component {
  constructor() {
    super();
    this.state = {
      color: 'red',
    };
  }

  handleColor = () => {            // 2.현재 compo의 handlecolor함수실행
    this.setState({                // 2-1 setState함수실행 > blue변경
      color: 'blue'
    })
  }

  render() {                       // 3. render함수호출
    return (                       // 4. 바뀐state값 반영하여 h1글자 색 변경
      <div>                    
        <h1 style={{ color: this.state.color }}>Class Component | State</h1>
        <button onClick={this.handleColor}>Click</button>       
      </div>                                   // 1.onclick event발생>this.hand~  
    );
  }
}

export default State;

 

 

 

ex2) 위의 inline style(태그에 바로 스타일 주는 형태)은 유지보수에 좋지않음

     > state에 따라 className바뀌게 하여 style변경

import React, { Component } from 'react';

class State extends Component {
  constructor() {
    super();
    this.state = {
      isRed: true,
    };
  }

  handleColor = () => {
    this.setState({
      isRed: !this.state.isRed
    })
  }

  render() {
    return (
      <div>
        <h1 className={isRed ? "red" : "blue"}>Class Component | State</h1>
        <button onClick={this.handleColor}>Click</button>
      </div>
    );
  }
}

export default State;

 

 

 

 

ex) 부모의 state > 자식에게

// Parent.js

import React from 'react';
import Child from '../pages/Child/Child';

class Parent extends React.Component {
  constructor() {
    super();
    this.state = {
      color: 'red'
    };
  }

  render() {
    return (
      <div>
        <h1>Parent Component</h1>
				<Child titleColor={this.state.color}/>
      </div>
    );
  }
}

export default Parent;
// Child.js

import React from 'react';

class Child extends React.Component {
  render() {
		console.log("이값은뭘까?", this.props.titleColor);

    return (
      <div>
        <h1 style={{color : this.props.titleColor}}>Child Component</h1>
      </div>
    );
  }
}

export default Child;

 

 

 

 

> ex) props로 state와 event handler넘기기

import React from 'react';
import Child from '../pages/Children/Children';

class Parent extends React.Component {
  constructor() {
    super();
    this.state = {
      color: 'red'
    };
  }

  changeColor = () => {
    this.setState({
      color: 'blue'
    })
  }

  render() {
    return (
      <div>
        <h1>Parent Component</h1>
        <Child titleColor={this.state.color} changeColor={this.changeColor}/>
      </div>
    );
  }
}

export default State;
import React from 'react';

class Child extends React.Component {
  render() {
		// console.log(this.props);

    return (
      <div>
        <h1 style={{color : this.props.titleColor}}>Child Component</h1>
        <button onClick={this.props.changeColor}>Click</button>
      </div>
    );
  }
}

export default State;

 

 

 

 


 

 

 

 

 

여러 state 관리

 

 

 

 

 하나의 state를 사용해서 여러 state관리하기

 

  const [title, setTitle] = useState("");
  const [amount, setAmount] = useState("");
  const [date, setDate] = useState("");
  
  //위의 3개의 state를 하나의 state에 담는다.
  const [userInput, setUserInput] = useState({
    title: "",
    amount: "",
    date: "",
  });

 

 

title만 변경할 때 나머지 2개의 state도 가져와서 잃어버리지않도록 ...userInput로 이전의 데이터를 복사하고

새로 업데이트된 값을 덮어쓴다.

하지만, 이 방식은 오류가 발생한다. (counter manage같은 경우) 

동시에 많은 state를 업데이터한다면 오래되거나 잘못된 state snapshot에 의존할 수도 있게된다.

  const titleChanageHandle = (event) => {
    setUserInput({
      ...userInput,         [이전상태에 의존]
      title: event.target.value,
    });

 

 

따라서,  '이전 state에 따라 state가 update된다면' setUserInput함수를 불러와서 함수를 pass in 시켜야 한다.

이 경우에는 state가 항상 최신상태이다. ( 모든 계획된 state update를 기억 )

  const titleChanageHandle = (event) => {
   setUserInput((prevState) => {
      return { ...prevState, title: event.target.value };
    });

 

 

 

 



 

 

state 끌어올리기

 

 

 

Lifting State Up

하위의 component에서 생성된 데이터를 상위의 component로 pass

 

1. 상위의 컴포넌트에서 데이터를 불러올 함수를 만든다 (함수를 pointer로 data를 pass한다.)

2. 만든함수를 props로 하위의 컴포넌트로 넘겨서 데이터에 접근하여 줍줍한다.

( 자식-자식간에 데이터를 주고받을 수 없다. 항상 단계별로 접근해야한다.)

 

 

 

 

상위 컴포넌트 App에서 하위컴포넌트의 데이터를 가져오려고한다.

하위의 '데이터'를 가져오기위해 데이터가져오기함수를 props로 하위에 넘겨준다.

function App() {
  const 데이터가져오기함수 = (데이터) => {
    console.log(데이터);
  };

  return (
    <div>
      <자식컴포넌트 데이터가져오기함수={데이터가져오기함수} />
    </div>
  );
}

 

하위컴포넌트에서 props로 '데이터가져오기함수'를받아서 하위의 데이터를 수집하는 함수에 추가해준다.

const 자식 = (props) => {
  const 어떤함수 = () => {
    const 데이터 = {
      어쩌고저쩌고
    };
    props.데이터가져오기함수(데이터);
  };
  
  return...

 

 

예시)

const NewExpense = ( ) => {
  const saveExpenseDataHandler = (enteredExpenseData) => {
    const expenseData = {
      ...enteredExpenseData,
      id: Math.random().toString(),
    };
    
  return (
      <ExpenseForm onSaveExpenseData={saveExpenseDataHandler} />
    );
  };
const ExpenseForm = (props) => {

  const sumitHandler = (event) => {
    event.preventDefault();

    const expenseData = {
      title: enteredtitle,
      amount: enteredamount,
      date: new Date(entereddate),
    };
    props.onSaveExpenseData(expenseData);

    setEnteredTitle("");
    setEnteredAmount("");
    setEnteredDate("");
  };

 

 

 

 

 

 

 

 

반응형

'Archive' 카테고리의 다른 글

[Node.js] Protocol / Port / URL  (0) 2021.09.13
[Node.js] 비동기  (0) 2021.09.13
[Node.js] Node.js 기본  (0) 2021.09.12
[21.09.02] Javascript reverse num  (0) 2021.09.02
[REACT] JSX / Component  (0) 2021.08.30