From d3507d138437aa02fec4ed21ce145de0f4a3290a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryan=20LIU=28=E5=8A=89=E5=AD=90=E7=9D=BF=29?= Date: Mon, 2 Feb 2026 16:01:35 +0800 Subject: [PATCH 1/2] This PR fixes a memory leak caused by missing removeEventListener calls in component unmount. All event listeners are now properly cleaned up. --- fixtures/concurrent/time-slicing/src/index.js | 38 +++++++++---------- 1 file changed, 19 insertions(+), 19 deletions(-) diff --git a/fixtures/concurrent/time-slicing/src/index.js b/fixtures/concurrent/time-slicing/src/index.js index 73ea91fddfa9..58516978776b 100644 --- a/fixtures/concurrent/time-slicing/src/index.js +++ b/fixtures/concurrent/time-slicing/src/index.js @@ -36,20 +36,25 @@ class App extends PureComponent { } componentDidMount() { - window.addEventListener('keydown', e => { + this.handleKeydown = e => { if (e.key.toLowerCase() === '?') { e.preventDefault(); this.setState(state => ({ showClock: !state.showClock, })); } - }); + }; + window.addEventListener('keydown', this.handleKeydown); + } + + componentWillUnmount() { + window.removeEventListener('keydown', this.handleKeydown); } handleChartClick = e => { if (this.state.showDemo) { if (e.shiftKey) { - this.setState({showDemo: false}); + this.setState({ showDemo: false }); } return; } @@ -63,9 +68,8 @@ class App extends PureComponent { return; } this._ignoreClick = true; - startTransition(() => { - this.setState({showDemo: true}, () => { + this.setState({ showDemo: true }, () => { this._ignoreClick = false; }); }); @@ -73,18 +77,18 @@ class App extends PureComponent { debouncedHandleChange = _.debounce(value => { if (this.state.strategy === 'debounced') { - this.setState({value: value}); + this.setState({ value: value }); } }, 1000); renderOption(strategy, label) { - const {strategy: currentStrategy} = this.state; + const { strategy: currentStrategy } = this.state; return ( @@ -93,10 +97,10 @@ class App extends PureComponent { handleChange = e => { const value = e.target.value; - const {strategy} = this.state; + const { strategy } = this.state; switch (strategy) { case 'sync': - this.setState({value}); + this.setState({ value }); break; case 'debounced': this.debouncedHandleChange(value); @@ -104,7 +108,7 @@ class App extends PureComponent { case 'async': // TODO: useTransition hook instead. startTransition(() => { - this.setState({value}); + this.setState({ value }); }); break; default: @@ -113,7 +117,7 @@ class App extends PureComponent { }; render() { - const {showClock} = this.state; + const { showClock } = this.state; const data = this.getStreamData(this.state.value); return (
@@ -123,7 +127,7 @@ class App extends PureComponent { {this.renderOption('async', 'Concurrent')}
)} -
+
); } -} - -const container = document.getElementById('root'); -const root = createRoot(container); -root.render(); +} \ No newline at end of file From a5cf8b4c7965bcfb635ea2318798203eef9214d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ryan=20LIU=28=E5=8A=89=E5=AD=90=E7=9D=BF=29?= Date: Mon, 2 Feb 2026 16:25:30 +0800 Subject: [PATCH 2/2] Update fixtures/concurrent/time-slicing/src/index.js Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- fixtures/concurrent/time-slicing/src/index.js | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/fixtures/concurrent/time-slicing/src/index.js b/fixtures/concurrent/time-slicing/src/index.js index 58516978776b..034470a888e3 100644 --- a/fixtures/concurrent/time-slicing/src/index.js +++ b/fixtures/concurrent/time-slicing/src/index.js @@ -143,4 +143,8 @@ class App extends PureComponent { ); } -} \ No newline at end of file +} + +const container = document.getElementById('root'); +const root = createRoot(container); +root.render(); \ No newline at end of file