본문 바로가기

공부 자료/리액트[React]

[React] 자식 컴포넌트에서 부모 컴포넌트로 데이터 전달

state를 활용한 컴포넌트 사이의 데이터 전달

 

기존에는 부모 컴포넌트에서 props를 통해 자식 컴포넌트는 데이터를 읽어올 수 있고,

자식 컴포넌트에서 해당 변수를 변경하더라도 부모 컴포넌트에는 영향을 미치지 않았는데 state를 활용하면 이가 가능하다

 

이를 가능하게 하기 위해서는 자식 컴포넌트가 부모 컴포넌트에게서 변수와 해당 변수를 변경할 수 있는 set 함수를

함께 받아오면 되는 것인데, 예시를 통해 더 자세히 알아보고자 한다

 

 

[한 컴포넌트 안에서 모든 동작이 이루어지는 경우]

import {useState} from 'react';

function UserList(){
    const[user, setUser] = useState({name:'', age:'', address:'', tel:''});
    const [userList, setUserList] = useState([]);
    const change = (e) => {
      let name = e.target.name;
      let value = e.target.value;
      setUser({...user, [name] : value});
    }
    const addUser = () =>{
        setUserList([...userList, user]);
        setUser({name:'', age:'', address:'', tel:''});
    }
    return (
        <div className="App">
          이름 : <input type="text" name="name" value={user.name} onChange={change} /><br/>
          나이 : <input type="text" name="age" value={user.age} onChange={change}/><br/>
          주소 : <input type="text" name="address" value={user.address} onChange={change}/><br/>
          전화 : <input type="text" name="tel" value={user.tel} onChange={change}/><br/><br/>

          <button onClick={addUser}>추가</button><br/><br/>

			// (1)
            {userList.length>0 && <table border="1"> 
              <tbody>
                <tr><th>이름</th><th>나이</th><th>주소</th><th>전화번호</th></tr>
                {userList.map((item) =>
                    (
                     <tr key={item.name}>
                        <td>{item.name}</td>
                        <td>{item.age}</td>
                        <td>{item.address}</td>
                        <td>{item.tel}</td>
                     </tr>   
                    )
                )}
              </tbody>
            </table>}
        </div>
    );
}

export default UserList;

(1) 특정 조건을 만족했을 때 태그를 보이게 하고 싶은 경우 사용하는 것으로, 조건을 만족했을 때 변경할 태그를 중괄호로 감싼 후 { (조건절) && (태그)} 의 형태를 이루면, 왼쪽 조건절이 T일 경우 왼쪽의 태그가 출력

 


위의 컴포넌트는 한 컴포넌트 내에서 이름/나이/주소/전화번호를 입력한 후 버튼을 클릭하면 아래 리스트에 적용되는 형태인데,

입력하는 것을 자식 컴포넌트(UserAdd) / 리스트로 출력되는 것을 부모 컴포넌트(UserTable)로 컴포넌트를 분리해 볼 것이다

 

컴포넌트를 분리할 경우 부모 컴포넌트가 자식 컴포넌트에서 입력한 데이터를 가지고 와야 하는데,

이 때 사용하는 것이 state이다.

 

 

[부모 컴포넌트 UserTable.js]

import {useState} from 'react';
import UserAdd from './UserAdd';

function UserTable(){
    const [userList, setUserList] = useState([]);

    return (
        <div className="App">
            {/* (1) */}
            <UserAdd userList={userList} setUserList={setUserList}/>
            
            {userList.length>0 && <table border="1"> 
              <tbody>
                <tr><th>이름</th><th>나이</th><th>주소</th><th>전화번호</th></tr>
                {userList.map((item) =>
                    (
                     <tr key={item.name}>
                        <td>{item.name}</td>
                        <td>{item.age}</td>
                        <td>{item.address}</td>
                        <td>{item.tel}</td>
                     </tr>   
                    )
                )}
              </tbody>
            </table>}
        </div>
    );
}

export default UserTable;

- 전체 코드와 다른점은 거의 없고 (1)과 같이 부모 컴포넌트에 자식 컴포넌트를 가지고 왔다는 차이가 존재

(1) 자식 컴포넌트를 출력

: 자식 컴포넌트에서 입력한 값을 이용해 아래 리스트에 출력해 줘야 하기 때문에 변경되어야 하는 userList와 이를 변경하는 set함수인 userList를 자식 컴포넌트에게 넘겨줌

 

 

[자식 컴포넌트 UserAdd.js]

import {useState} from 'react';

function UserAdd({userList, setUserList}){ // (1)
    const[user, setUser] = useState({name:'', age:'', address:'', tel:''});
    
    const change = (e) => {
      let name = e.target.name;
      let value = e.target.value;
      setUser({...user, [name] : value});
    }

    const addUser = () =>{
        setUserList([...userList, user]);
        setUser({name:'', age:'', address:'', tel:''});
    }
    
    return(
        <>
            이름 : <input type="text" name="name" value={user.name} onChange={change} /><br/>
            나이 : <input type="text" name="age" value={user.age} onChange={change}/><br/>
            주소 : <input type="text" name="address" value={user.address} onChange={change}/><br/>
            전화 : <input type="text" name="tel" value={user.tel} onChange={change}/><br/><br/>

            <button onClick={addUser}>추가</button><br/><br/>
        </>
    )
}

export default UserAdd;

(1) 부모 컴포넌트로부터 받은 userList와 set 함수를 가져옴

- 이를 이용해 추가 버튼을 클릭하면 해당 userList에 user가 추가되도록 로직을 작성

 


하나의 컴포넌트를 2개의 컴포넌트로 나누는 것

부모의 컴포넌트에 있는 데이터를 자식 컴포넌트에서 변경하는 것

 

어려워 보이기는 하지만 실상 이해하면 많이 어렵지 않은 로직임을 알 수 있다:)