
React는 기본적으로 단방향적인 데이터흐름을 가지고있다.
부모 컴포넌트에서 데이터를 뿌려서 자식 컴포넌트들이 그것을 이용해 사용할 수 있어도
일반적으로 자식 컴포넌트에서 부모컴포넌트로 향하는 역방향의 데이터흐름은 가지지않는다.
다만, 콜백함수를 통해 상태 끌어올리기가 가능하다. 상태 끌어올리기란 부모 컴포넌트에서 상태를 관리하고, 자식 컴포넌트에서 부모 컴포넌트로부터 제공받은 콜백함수를 사용하여, 부모 컴포넌트에서 상태를 업데이트 할 수 있는것이다.
예시를 통해 보자.


부모 컴포넌트(App.js)는 자식컴포넌트(NewTask)에게 상태에 관련한 콜백함수를 전달한다.
이를 자식 컴포넌트는 콜백함수를 통하여 부모 컴포넌트의 상태를 변경한다.
변경된 상태는 또 다른 자식 컴포넌트(NewTask2, NewTask3)에게 전달하여 이 컴포넌트들은 해당 상태를 사용할 수 있어서 재사용성이 용이해진다.
부모 컴포넌트인 App.js
App.js
import React, {useState} from 'react';
import NewTask from './NewTask';
import NewTask2 from './NewTask2';
import NewTask3 from './NewTask3';
function App() {
// tasks 상태 선언
const [tasks, setTasks] = useState([]);
// 전달할 콜백함수
const taskAddHandler = (task) => {
setTasks((prevTasks) => prevTasks.concat(task))
}
return (
<div>
<p>NewTask 자식 컴포넌트에서 부모로부터 콜백함수를 전달받아 데이터 상향식 전달</p>
<NewTask onAddTask={taskAddHandler} />
<p>부모 컴포넌트에서 데이터 보여주기</p>
<ul>
{tasks.map((task) => (
<li key={task.id}>{task.text}</li>
))}
</ul>
<p>NewTask2 자식 컴포넌트에서 데이터 보여주기</p>
<NewTask2 tasksData={tasks} />
<p>NewTask3 자식 컴포넌트에서 데이터 보여주기</p>
<NewTask3 tasksData={tasks} />
</div>
);
}
export default App;
자식 컴포넌트인 NewTask.js
NewTask.js
import React, { useState } from 'react';
const NewTask = (props) => {
const [taskText, setTaskText] = useState('');
const createTask = () => {
const generatedId = Math.random().toString();
const createdTask = { id: generatedId, text : taskText };
// 자식 컴포넌트에서 props로 받은 함수 호출(콜백함수)
props.onAddTask(createdTask);
// 입력 필드 초기화
setTaskText('');
};
return (
<div>
<input
type="text"
value={taskText}
onChange={(e) => setTaskText(e.target.value)}
/>
<button onClick={createTask}>Add Task</button>
</div>
)
}
export default NewTask;
또다른 자식 컴포넌트(NewTask2, NewTask3)
NewTask2.js
import React from 'react';
const NewTask = (props) => {
return (
<ol>
{props.tasksData.map((tasksData) => (
<li key={tasksData.id}>{tasksData.text}</li>
))}
</ol>
)
}
export default NewTask;
NewTask3.js
import React from 'react';
const NewTask3 = (props) => {
return (
<ol>
{props.tasksData.map((tasksData) => (
<h4 key={tasksData.id}>{tasksData.text}</h4>
))}
</ol>
)
}
export default NewTask3;