<html>
<head>
<title>This is the title of the webpage!</title>
</head>
<body>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.13.1/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.13.1/umd/react-dom.production.min.js"></script>
<div id="root"></div>
</body>
</html>
function ComponentWithOuterFunctionUseCallback() {
const [state, setState] = React.useState();
function functionToTest(evt) {
evt.preventDefault();
setState('test');
}
const testFunction = React.useCallback(functionToTest, []);
return React.createElement('button', {onClick: testFunction}, 'Test click');
}
function ComponentWithUseCallback() {
const [state, setState] = React.useState();
const testFunction = React.useCallback(evt => {evt.preventDefault(); setState('test');}, []);
return React.createElement('button', {onClick: testFunction}, 'Test click');
}
function ComponentWithInlineFunction() {
const [state, setState] = React.useState();
function testFunction(evt) {
evt.preventDefault();
setState('test');
}
return React.createElement('button', {onClick: testFunction}, 'Test click');
}
function ComponentWithArrowFunction() {
const [state, setState] = React.useState();
const testFunction = (evt) => {
evt.preventDefault();
setState('test');
}
return React.createElement('button', {onClick: testFunction}, 'Test click');
}
const testFunctionInlineOutside = function(evt, setState) {
return evt.preventDefault();
setState('test');
}
function ComponentWithInlineFunctionOutside() {
const [state, setState] = React.useState();
return React.createElement('button', {onClick: (evt) => testFunctionArrowOutside(evt, setState)}, 'Test click');
}
const testFunctionArrowOutside = (evt, setState) => {
evt.preventDefault();
setState('test');
}
function ComponentWithArrowFunctionOutside() {
const [state, setState] = React.useState();
return React.createElement('button', {onClick: (evt) => testFunctionArrowOutside(evt, setState)}, 'Test click');
}
ReactDOM.render(React.createElement(ComponentWithOuterFunctionUseCallback), document.getElementById('root'))
ReactDOM.render(React.createElement(ComponentWithUseCallback), document.getElementById('root'))
ReactDOM.render(React.createElement(ComponentWithInlineFunction), document.getElementById('root'))
ReactDOM.render(React.createElement(ComponentWithArrowFunction), document.getElementById('root'))
ReactDOM.render(React.createElement(ComponentWithInlineFunctionOutside), document.getElementById('root'))
ReactDOM.render(React.createElement(ComponentWithArrowFunctionOutside), document.getElementById('root'))
--enable-precise-memory-info
flag.
Test case name | Result |
---|---|
ComponentWithOuterFunctionUseCallback | |
ComponentWithUseCallback | |
ComponentWithInlineFunction | |
ComponentWithArrowFunction | |
ComponentWithInlineFunctionOutside | |
ComponentWithArrowFunctionOutside |
Test name | Executions per second |
---|---|
ComponentWithOuterFunctionUseCallback | 404100.9 Ops/sec |
ComponentWithUseCallback | 419080.1 Ops/sec |
ComponentWithInlineFunction | 358398.7 Ops/sec |
ComponentWithArrowFunction | 358240.9 Ops/sec |
ComponentWithInlineFunctionOutside | 359661.9 Ops/sec |
ComponentWithArrowFunctionOutside | 354462.6 Ops/sec |
I'll break down the benchmark definition and test cases to explain what's being tested.
Benchmark Definition
The benchmark definition is essentially how the React library renders a specific component. The script preparation code defines four different components: ComponentWithOuterFunctionUseCallback
, ComponentWithUseCallback
, ComponentWithInlineFunction
, ComponentWithArrowFunction
, ComponentWithInlineFunctionOutside
, and ComponentWithArrowFunctionOutside
. Each component has a different implementation of the onClick
event handler.
Test Cases
There are six test cases, each rendering one of the components defined above. The test case names correspond to the component name. The benchmark definition is executed by rendering the corresponding component using ReactDOM.render
.
What's being tested?
The benchmark tests how the React library performs when rendering different types of event handlers: traditional function expressions (e.g., ComponentWithOuterFunctionUseCallback
), arrow functions (e.g., ComponentWithArrowFunction
), and anonymous function calls with external variables (e.g., ComponentWithInlineFunctionOutside
). The test also compares the performance of using a callback function (e.g., ComponentWithUseCallback
) versus defining it as an inline function.
Options compared
The benchmark tests three main options:
ComponentWithOuterFunctionUseCallback
.ComponentWithArrowFunction
.ComponentWithInlineFunctionOutside
.The test also includes two additional variants:
ComponentWithUseCallback
.Why is this benchmark interesting?
This benchmark is interesting because it tests how different approaches to event handling affect performance in React. The results can help developers understand which approach is most efficient for their use case and optimize their code accordingly.
The benchmark also highlights the importance of considering the performance implications of coding decisions, even those that may seem minor or trivial at first glance.