refactor: Convert App class component to functional component

This commit is contained in:
2025-07-07 17:22:56 +00:00
committed by Tanner Collin
parent 5cdbf6ef54
commit 633429c976

View File

@@ -1,4 +1,4 @@
import React from 'react';
import React, { useState, useEffect, useRef, useCallback } from 'react';
import { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
import localForage from 'localforage';
import './Style-light.css';
@@ -15,70 +15,63 @@ import Submit from './Submit.js';
import Results from './Results.js';
import ScrollToTop from './ScrollToTop.js';
class App extends React.Component {
constructor(props) {
super(props);
function App() {
const [theme, setTheme] = useState(localStorage.getItem('theme') || '');
const cache = useRef({});
const [isFullScreen, setIsFullScreen] = useState(!!document.fullscreenElement);
this.state = {
theme: localStorage.getItem('theme') || '',
};
const updateCache = useCallback((key, value) => {
cache.current[key] = value;
}, []);
this.cache = {};
}
updateCache = (key, value) => {
this.cache[key] = value;
}
light() {
this.setState({ theme: '' });
const light = () => {
setTheme('');
localStorage.setItem('theme', '');
}
};
dark() {
this.setState({ theme: 'dark' });
const dark = () => {
setTheme('dark');
localStorage.setItem('theme', 'dark');
}
};
black() {
this.setState({ theme: 'black' });
const black = () => {
setTheme('black');
localStorage.setItem('theme', 'black');
}
};
red() {
this.setState({ theme: 'red' });
const red = () => {
setTheme('red');
localStorage.setItem('theme', 'red');
}
};
componentDidMount() {
if (!this.cache.length) {
useEffect(() => {
if (Object.keys(cache.current).length === 0) {
localForage.iterate((value, key) => {
this.updateCache(key, value);
updateCache(key, value);
}).then(() => {
console.log('loaded cache from localforage');
});
console.log('loaded cache from localforage');
}
}
}, [updateCache]);
goFullScreen() {
const goFullScreen = () => {
if ('wakeLock' in navigator) {
navigator.wakeLock.request('screen');
}
document.body.requestFullscreen({ navigationUI: 'hide' }).then(() => {
window.addEventListener('resize', () => this.forceUpdate());
this.forceUpdate();
});
document.body.requestFullscreen({ navigationUI: 'hide' });
};
exitFullScreen() {
document.exitFullscreen().then(() => {
this.forceUpdate();
});
const exitFullScreen = () => {
document.exitFullscreen();
};
render() {
const theme = this.state.theme;
useEffect(() => {
const onFullScreenChange = () => setIsFullScreen(!!document.fullscreenElement);
document.addEventListener('fullscreenchange', onFullScreenChange);
return () => document.removeEventListener('fullscreenchange', onFullScreenChange);
}, []);
useEffect(() => {
if (theme === 'dark') {
document.body.style.backgroundColor = '#1a1a1a';
} else if (theme === 'black') {
@@ -88,49 +81,49 @@ class App extends React.Component {
} else {
document.body.style.backgroundColor = '#eeeeee';
}
}, [theme]);
const fullScreenAvailable = document.fullscreenEnabled ||
document.mozFullscreenEnabled ||
document.webkitFullscreenEnabled ||
document.msFullscreenEnabled;
const fullScreenAvailable = document.fullscreenEnabled ||
document.mozFullscreenEnabled ||
document.webkitFullscreenEnabled ||
document.msFullscreenEnabled;
return (
<div className={theme}>
<Router>
<div className='container menu'>
<p>
<Link to='/'>QotNews</Link>
return (
<div className={theme}>
<Router>
<div className='container menu'>
<p>
<Link to='/'>QotNews</Link>
<span className='theme'><a href='#' onClick={() => this.light()}>Light</a> - <a href='#' onClick={() => this.dark()}>Dark</a> - <a href='#' onClick={() => this.black()}>Black</a> - <a href='#' onClick={() => this.red()}>Red</a></span>
<br />
<span className='slogan'>Hacker News, Reddit, Lobsters, and Tildes articles rendered in reader mode.</span>
</p>
<Route path='/(|search)' component={Search} />
<Route path='/(|search)' component={Submit} />
{fullScreenAvailable &&
<Route path='/(|search)' render={() => !document.fullscreenElement ?
<button className='fullscreen' onClick={() => this.goFullScreen()}>Enter Fullscreen</button>
:
<button className='fullscreen' onClick={() => this.exitFullScreen()}>Exit Fullscreen</button>
} />
}
</div>
<span className='theme'><a href='#' onClick={() => light()}>Light</a> - <a href='#' onClick={() => dark()}>Dark</a> - <a href='#' onClick={() => black()}>Black</a> - <a href='#' onClick={() => red()}>Red</a></span>
<br />
<span className='slogan'>Hacker News, Reddit, Lobsters, and Tildes articles rendered in reader mode.</span>
</p>
<Route path='/(|search)' component={Search} />
<Route path='/(|search)' component={Submit} />
{fullScreenAvailable &&
<Route path='/(|search)' render={() => !isFullScreen ?
<button className='fullscreen' onClick={() => goFullScreen()}>Enter Fullscreen</button>
:
<button className='fullscreen' onClick={() => exitFullScreen()}>Exit Fullscreen</button>
} />
}
</div>
<Route path='/' exact render={(props) => <Feed {...props} updateCache={this.updateCache} />} />
<Switch>
<Route path='/search' component={Results} />
<Route path='/:id' exact render={(props) => <Article {...props} cache={this.cache} />} />
</Switch>
<Route path='/:id/c' exact render={(props) => <Comments {...props} cache={this.cache} />} />
<Route path='/' exact render={(props) => <Feed {...props} updateCache={updateCache} />} />
<Switch>
<Route path='/search' component={Results} />
<Route path='/:id' exact render={(props) => <Article {...props} cache={cache.current} />} />
</Switch>
<Route path='/:id/c' exact render={(props) => <Comments {...props} cache={cache.current} />} />
<BackwardDot />
<ForwardDot />
<BackwardDot />
<ForwardDot />
<ScrollToTop />
</Router>
</div>
);
}
<ScrollToTop />
</Router>
</div>
);
}
export default App;