Callback Handlers and Lifting State in React – Component Communication and Shared Data Management

In React, props allow data to flow from parent to child, but not the other way around. To enable upward communication, we use callback handlers — functions passed down as props and invoked in child components. This article explains how to define and use callback handlers, and introduces the concept of lifting state to manage shared data at the appropriate component level.

callback-handlerlifting-statedata filteringcomponent communication

~2 min read • Updated Oct 22, 2025

Introduction


In React, props are used to pass data from parent to child components. But to communicate from child to parent, we use callback handlers. These are functions defined in the parent, passed down via props, and invoked in the child to send data or trigger actions upward.


Defining a Callback Handler


In the example below, the App component defines a handleSearch function and passes it to the Search component:


const App = () => {
  const stories = [ ... ];
  const handleSearch = (event) => {
    console.log(event.target.value);
  };

  return (
    
); };

In the Search component, the function is received via props and called inside the input’s change handler:


const Search = (props) => {
  const [searchTerm, setSearchTerm] = React.useState('');

  const handleChange = (event) => {
    setSearchTerm(event.target.value);
    props.onSearch(event);
  };

  return (
    
); };

Lifting State


If the parent component needs access to a piece of state, it’s better to define that state in the parent. In this case, we move searchTerm from Search to App:


const App = () => {
  const stories = [ ... ];
  const [searchTerm, setSearchTerm] = React.useState('');

  const handleSearch = (event) => {
    setSearchTerm(event.target.value);
  };

  return (
    
); };

Filtering Data with State


Now we can use searchTerm to filter the stories before passing them to the List component:


const searchedStories = stories.filter((story) =>
  story.title.includes(searchTerm)
);

Then pass the filtered list:


<List list={searchedStories} />

Conclusion


Callback handlers allow child components to communicate with parents. Lifting state ensures shared data is managed at the right level. Together, these patterns make React components more maintainable, scalable, and interactive.


Written & researched by Dr. Shahin Siami