I decided to write up this post because whenever I start a new React project, I find myself googling the same question. So, how to handle events on a stateless (or dumb) React component?
Let's say we want to build a Markdown previewer in React. The components we'll need are:
-
<EditingBox />
, to write our Markdown in -
<PreviewBox />
, to see the Markdown we typed rendered
Logically, these are the only two components we need. But where will we put the state? Both <EditingBox />
and <PreviewBox />
are hierarchically on the same level, so we can create a parent component to render them and contain the state. This is called lifting the state up. Let's call that component <App />
.
Note: the below code uses the Marked.js library.
const EditingBox = (props) => {
return <textarea>{props.input}</textarea>;
}
const PreviewBox = (props) => {
return <div dangerouslySetInnerHTML={{__html: marked(props.input)}}></div>;
}
class App extends React.Component {
state = {
input: `# Welcome to my React Markdown Previewer!`
};
render() {
return (
<div class="container">
<EditingBox {...this.state} />
<PreviewBox {...this.state} />
</div>
);
}
}
ReactDOM.render(<App />, document.getElementById("app"));
As we said, the <App />
component houses the state and renders the other two components. Now, we need a function that listens for change in the <EditingBox />
component and updates the state so that <PreviewBox />
can then get the updated state and display it.
This function will live in the <App />
component, because the state and all the functions that update it must live in the same component. It can be declared as follows:
handleChange(event) {
this.setState({
input: event.target.value
});
}
Now, we can pass down this method to <EditingBox />
render() {
return (
<div class="container">
<EditingBox {...this.state} onChange={() => this.handleChange(event)} />
<PreviewBox {...this.state} />
</div>
);
}
}
so that it can be used inside <EditingBox />
as a regular prop
const EditingBox = (props) => {
return <textarea onChange={() => props.onChange()}>{props.input}</textarea>;
}
Here is the full application
Thank you for reading. Until next time 👋
Cover photo by me.