React/velopert_react

배열에 데이터 삽입하기(배열 데이터 렌더링 및 관리)

느리지만 꾸준하게 2021. 8. 20. 17:07

자식 컴포넌트가 부모한테 값 전달하는 방법에 대해서 알아보자.

 

App컴포넌트 내부에서 handleCreate라는 메소드를 만든다. 그리고 그 메소드를 자식컴포넌트한테 props로 전달을 해주고 여기에서 props로 전달한 함수를 호출시켜서 data값이 App한테 들어가게끔 작성을 해준다.

자식 컴포넌트(주황) = > 부모 컴포넌트(남색) 값 전달과정

 

코드상으로 확인해보자.

만든 컴포넌트들이 아래와 같이 있는데,  App.js에 handleCreate라는 함수를 만들어준다. data를 파라미터로 가져와서

지금단계에서 console.log(data);라고 확인만 해준다. 또 PhoneForm에다 oncreate라는 값으로 handleCreate를 전달해 준다.

class App extends Component {

  handleCreate = (data) => {
    console.log(data);
  }
  render() {
    return (
      <div>
        <PhoneForm onCreate={this.handleCreate} />
      </div>
    );
  }
}

export default App;

PhoneForm 컴포넌트로 와서 submit 버튼을 만들어준다. html에서 form속성이 submit 버튼을 누르면 새로고침이 되게 되어 있는데 이것을 방지시켜준다.

            <form>
                <input
                    name="name"
                    placeholder="이름"
                    onChange={this.handleChange}
                    value={this.state.name}
                />
                <input
                    name="phone"
                    placeholder="전화번호"
                    onChange={this.handleChange}
                    value={this.state.phone}
                />
                <button type="submit">등록</button>
                <div>
                    {this.state.name} {this.state.phone}
                </div>
            </form>

handleSubmit 함수를 구현해준다. 페이지가 reloading되는 것을 방지해 주기 위해서 e.preventDefault()라는 함수를 호출해준다. preventDefault()는 원래 해야하는 작업을 하지 않는 것이다. 원래는 등록하면 버튼을 값을 입력하고 버튼을 누르면 새로고침이 되어지는데 preventDefault()가 방지시켜주는 것이다.

 

handleSubmitform에다가 onSubmit라는 props로 전달을 해준다. 버튼을 클릭해도 새로고침이 되지 않는다.

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

    handleSubmit = (e) => {
        e.preventDefault();
    }

    render() {
        return (
            <form onSubmit={this.handleSubmit}>

그리고 props로 받았던 onCreate함수를 PhoneForm에서 호출해준다. 편의상 this.satae를 해줘도 상관없다. 이렇게 해서 브라우저에서 개발자도구를 켜서 name값과 phone값이 정확히 들어갔는지 봐준다.

    handleSubmit = (e) => {
        e.preventDefault();
        this.props.onCreate({
            name: this.state.name,
            phone: this.state.phone,
        })
    }
    handleSubmit = (e) => {
        e.preventDefault();
        this.props.onCreate(this.state);
    }

그럼 이제 App.js가 데이터를 받아왔으니까 이것을 App에 안에있는 상태에다가 담아주도록 한다. 

배열을 다루는 방법을 알아보자. state를 정의해주고 전화번호부 정보들을 information이라는 배열에 넣어준다.

 

그리고 나서 handleCreate가 발생하게 되면 data의 information안에 넣어주는데

아래와 같이하면 안된다. 왜냐? 리액트에서는 불변성을 꼭 유지해줘야 한다. 어떠한 값을 수정하게 될 때 언제나 setState를 사용해야 하고 또 그 내부에 있는 배열이나 객체를 바꾸게 될 때는 기존의 배열이나 객체를 수정하지 않고 그것을 기반으로 새로운 객체 혹은 배열을 만들어서 값을 주입해줘야 한다.

class App extends Component {
  state = {
    information: [],
  }

  handleCreate = (data) => {
    this.state.information.push(data);
    this.setState({
      information: this.state.information,
    })
  }

그래서 push를 사용하는 것이 아니라, concat이라는 배열 내장함수를 사용해야 한다. 그러면 기존에 있던 배열은 수정하지 않고 새로운 배열을 만들어서 그 배열에다가 사용자의 data를 집어넣어서 그 배열을 기존에 있던 배열자리에 넣어주는 작업을 하게된다.

아래와 같이 a, 1을 넣어주면 그 자리에 name값과 phone값이 각각 나타나게 된다.

class App extends Component {
  state = {
    information: [],
  }

  handleCreate = (data) => {
    this.setState({
      information: this.state.information.concat(data),
    })
  }

information값을 문자열 형태로 변환해서 밑에 자리에 보여주도록 한다. 처음에 아래와 같이 빈 배열이 나타난다.

  render() {
    return (
      <div>
        <PhoneForm onCreate={this.handleCreate} />
        {JSON.stringify(this.state.information)}
      </div>
    );
  }
}

handleCreate를 조금 더 간편하게 작성해보자. 이렇게 비구조할당 문법을 사용하면은 코드가 길어지는 걸 방지할 수 있고 가독성도 괜찮아진다.

  handleCreate = (data) => {
    const { information } = this.state;
    this.setState({
      information: information.concat(data),
    })
  }

 

그리고 PhoneForm 컴포넌트에서 뭔가 등록이 되면 input값들을 초기화 해주도록 하자.

    handleSubmit = (e) => {
        e.preventDefault();
        this.props.onCreate(this.state);
        this.setState({
            name: '',
            phone: '',
        })
    }

input값에 입력하면 기존에 보여지는 것들도 없애준다.

                <button type="submit">등록</button>
                <div>
                    {this.state.name} {this.state.phone}
                </div>
                
           
           =>
           
                <button type="submit">등록</button>

이번에는 데이터를 추가할 때 마다 각 데이터의 고유한 id값이 들어가지게 만들어준다. App.js에서 id라는 값을 일단 0으로 정해준다. 그리고 id를 아래와 같이 넣어준다.

데이터가 추가될 때마다 id값이 1씩 올라가지고 this자리에는 현재 id값이 들어가진다.

  id = 0;

  state = {
    information: [],
  }

  handleCreate = (data) => {
    const { information } = this.state;
    this.setState({
      information: information.concat({
        ...data,
        id: this.id++
      })
    });
  }

고유한 id값을 넣어준 이유는 배열에 있는 것들을 rendering 해줄 때 고유한 값인 key값이 있어야 한다. 그래서 넣어주었고 나중에 더 자세히 알아보자.

concat을 했을 때 ...data를 썼는데 이 방법 말고도 여러 방법이 있다.

  handleCreate = (data) => {
    const { information } = this.state;
    this.setState({
      information: information.concat({
        name: data.name,
        phone: data.phone,
        id: this.id++
      })
    });
  }

위에서 name값과 phone값을 날려주고 Object.assign이라는 함수를 사용한다. 앞에 {} 비어있는 객체를 넣어주고 data를 넣어준다. 즉 비어있는 객체에 data를 집어넣고 id도 집어넣고 한다는 것이다.

  handleCreate = (data) => {
    const { information } = this.state;
    this.setState({
      information: information.concat(Object.assign({}, data, {
        id: this.id++
      }))
    });
  }

 위에서 id값은 state에 따로 안넣어줬는데 id값은 rendering 되는 것이 아니기 때문에 굳이 setState를 통해서 넣어줄 필요가 없다. setState를 하는 이유는 어떠한 값이 수정됐을 때 re-rendering을 꼭 할려고 그러는데 id값은 re-rendering과는 관련이 없고 어떠한값을 추가할 때 참조하는 값이기 때문에 굳이 state에 넣어주지 않아도 된다. 

  id = 0;

  state = {
    information: [],
  }

  handleCreate = (data) => {
    const { information } = this.state;
    this.setState({
      information: information.concat(Object.assign({}, data, {
        id: this.id++
      }))
    });
  }

일단 결론적으로는 배열 내부에 id값도 넣어주는 방법을 알아보았다. 이후에 배열형식으로 된 것을 컴포넌트 형식으로 되게끔 하는 것을 작성하자.

 

 

 

<출처 : velopert(김 민준) 누구든지 하는 리액트: 초심자를 위한 react 핵심 강좌>

https://www.inflearn.com/course/react-velopert/dashboard

 

누구든지 하는 리액트: 초심자를 위한 react 핵심 강좌 - 인프런 | 강의

리액트를 누구든지 쉽고 재밌게 시작 할 수 있도록 만들어진 강좌입니다., React 핵심 강좌 초심자를 위한 리액트(React) 핵심 강좌입니다. 만약에 여러분이 리액트를 배우고 싶은데, 아직 뭐가 뭔

www.inflearn.com

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Operators/Spread_syntax

 

전개 구문 - JavaScript | MDN

전개 구문을 사용하면 배열이나 문자열과 같이 반복 가능한 문자를 0개 이상의 인수 (함수로 호출할 경우) 또는 요소 (배열 리터럴의 경우)로 확장하여, 0개 이상의 키-값의 쌍으로 객체로 확장시

developer.mozilla.org

https://developer.mozilla.org/ko/docs/Web/JavaScript/Reference/Global_Objects/Object/assign

 

Object.assign() - JavaScript | MDN

Object.assign() 메소드는 출처 객체로부터 모든 열거할 수 있는(enumerable) 하나 이상의 속성(own properties)들을 목표 객체로 복사합니다. 이는 수정된 목표 객체를 반환합니다.

developer.mozilla.org

 

'React > velopert_react' 카테고리의 다른 글

배열에서 데이터 제거하기  (0) 2021.08.20
배열 렌더링하기  (0) 2021.08.20
Input 상태 관리하기  (0) 2021.08.19
LyfeCycle API 소개 및 사용법 ⅱ  (0) 2021.08.19
LyfeCycle API 소개 및 사용법 ⅰ  (0) 2021.08.19