forked from tanner/qotnews
refactor: Convert App class component to functional component
This commit is contained in:
@@ -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 { BrowserRouter as Router, Route, Link, Switch } from 'react-router-dom';
|
||||||
import localForage from 'localforage';
|
import localForage from 'localforage';
|
||||||
import './Style-light.css';
|
import './Style-light.css';
|
||||||
@@ -15,70 +15,63 @@ import Submit from './Submit.js';
|
|||||||
import Results from './Results.js';
|
import Results from './Results.js';
|
||||||
import ScrollToTop from './ScrollToTop.js';
|
import ScrollToTop from './ScrollToTop.js';
|
||||||
|
|
||||||
class App extends React.Component {
|
function App() {
|
||||||
constructor(props) {
|
const [theme, setTheme] = useState(localStorage.getItem('theme') || '');
|
||||||
super(props);
|
const cache = useRef({});
|
||||||
|
const [isFullScreen, setIsFullScreen] = useState(!!document.fullscreenElement);
|
||||||
|
|
||||||
this.state = {
|
const updateCache = useCallback((key, value) => {
|
||||||
theme: localStorage.getItem('theme') || '',
|
cache.current[key] = value;
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
const light = () => {
|
||||||
|
setTheme('');
|
||||||
|
localStorage.setItem('theme', '');
|
||||||
};
|
};
|
||||||
|
|
||||||
this.cache = {};
|
const dark = () => {
|
||||||
}
|
setTheme('dark');
|
||||||
|
|
||||||
updateCache = (key, value) => {
|
|
||||||
this.cache[key] = value;
|
|
||||||
}
|
|
||||||
|
|
||||||
light() {
|
|
||||||
this.setState({ theme: '' });
|
|
||||||
localStorage.setItem('theme', '');
|
|
||||||
}
|
|
||||||
|
|
||||||
dark() {
|
|
||||||
this.setState({ theme: 'dark' });
|
|
||||||
localStorage.setItem('theme', 'dark');
|
localStorage.setItem('theme', 'dark');
|
||||||
}
|
};
|
||||||
|
|
||||||
black() {
|
const black = () => {
|
||||||
this.setState({ theme: 'black' });
|
setTheme('black');
|
||||||
localStorage.setItem('theme', 'black');
|
localStorage.setItem('theme', 'black');
|
||||||
}
|
};
|
||||||
|
|
||||||
red() {
|
const red = () => {
|
||||||
this.setState({ theme: 'red' });
|
setTheme('red');
|
||||||
localStorage.setItem('theme', 'red');
|
localStorage.setItem('theme', 'red');
|
||||||
}
|
};
|
||||||
|
|
||||||
componentDidMount() {
|
useEffect(() => {
|
||||||
if (!this.cache.length) {
|
if (Object.keys(cache.current).length === 0) {
|
||||||
localForage.iterate((value, key) => {
|
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) {
|
if ('wakeLock' in navigator) {
|
||||||
navigator.wakeLock.request('screen');
|
navigator.wakeLock.request('screen');
|
||||||
}
|
}
|
||||||
|
document.body.requestFullscreen({ navigationUI: 'hide' });
|
||||||
document.body.requestFullscreen({ navigationUI: 'hide' }).then(() => {
|
|
||||||
window.addEventListener('resize', () => this.forceUpdate());
|
|
||||||
this.forceUpdate();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
exitFullScreen() {
|
const exitFullScreen = () => {
|
||||||
document.exitFullscreen().then(() => {
|
document.exitFullscreen();
|
||||||
this.forceUpdate();
|
|
||||||
});
|
|
||||||
};
|
};
|
||||||
|
|
||||||
render() {
|
useEffect(() => {
|
||||||
const theme = this.state.theme;
|
const onFullScreenChange = () => setIsFullScreen(!!document.fullscreenElement);
|
||||||
|
document.addEventListener('fullscreenchange', onFullScreenChange);
|
||||||
|
return () => document.removeEventListener('fullscreenchange', onFullScreenChange);
|
||||||
|
}, []);
|
||||||
|
|
||||||
|
useEffect(() => {
|
||||||
if (theme === 'dark') {
|
if (theme === 'dark') {
|
||||||
document.body.style.backgroundColor = '#1a1a1a';
|
document.body.style.backgroundColor = '#1a1a1a';
|
||||||
} else if (theme === 'black') {
|
} else if (theme === 'black') {
|
||||||
@@ -88,6 +81,7 @@ class App extends React.Component {
|
|||||||
} else {
|
} else {
|
||||||
document.body.style.backgroundColor = '#eeeeee';
|
document.body.style.backgroundColor = '#eeeeee';
|
||||||
}
|
}
|
||||||
|
}, [theme]);
|
||||||
|
|
||||||
const fullScreenAvailable = document.fullscreenEnabled ||
|
const fullScreenAvailable = document.fullscreenEnabled ||
|
||||||
document.mozFullscreenEnabled ||
|
document.mozFullscreenEnabled ||
|
||||||
@@ -101,27 +95,27 @@ class App extends React.Component {
|
|||||||
<p>
|
<p>
|
||||||
<Link to='/'>QotNews</Link>
|
<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>
|
<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 />
|
<br />
|
||||||
<span className='slogan'>Hacker News, Reddit, Lobsters, and Tildes articles rendered in reader mode.</span>
|
<span className='slogan'>Hacker News, Reddit, Lobsters, and Tildes articles rendered in reader mode.</span>
|
||||||
</p>
|
</p>
|
||||||
<Route path='/(|search)' component={Search} />
|
<Route path='/(|search)' component={Search} />
|
||||||
<Route path='/(|search)' component={Submit} />
|
<Route path='/(|search)' component={Submit} />
|
||||||
{fullScreenAvailable &&
|
{fullScreenAvailable &&
|
||||||
<Route path='/(|search)' render={() => !document.fullscreenElement ?
|
<Route path='/(|search)' render={() => !isFullScreen ?
|
||||||
<button className='fullscreen' onClick={() => this.goFullScreen()}>Enter Fullscreen</button>
|
<button className='fullscreen' onClick={() => goFullScreen()}>Enter Fullscreen</button>
|
||||||
:
|
:
|
||||||
<button className='fullscreen' onClick={() => this.exitFullScreen()}>Exit Fullscreen</button>
|
<button className='fullscreen' onClick={() => exitFullScreen()}>Exit Fullscreen</button>
|
||||||
} />
|
} />
|
||||||
}
|
}
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<Route path='/' exact render={(props) => <Feed {...props} updateCache={this.updateCache} />} />
|
<Route path='/' exact render={(props) => <Feed {...props} updateCache={updateCache} />} />
|
||||||
<Switch>
|
<Switch>
|
||||||
<Route path='/search' component={Results} />
|
<Route path='/search' component={Results} />
|
||||||
<Route path='/:id' exact render={(props) => <Article {...props} cache={this.cache} />} />
|
<Route path='/:id' exact render={(props) => <Article {...props} cache={cache.current} />} />
|
||||||
</Switch>
|
</Switch>
|
||||||
<Route path='/:id/c' exact render={(props) => <Comments {...props} cache={this.cache} />} />
|
<Route path='/:id/c' exact render={(props) => <Comments {...props} cache={cache.current} />} />
|
||||||
|
|
||||||
<BackwardDot />
|
<BackwardDot />
|
||||||
<ForwardDot />
|
<ForwardDot />
|
||||||
@@ -131,6 +125,5 @@ class App extends React.Component {
|
|||||||
</div>
|
</div>
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
export default App;
|
export default App;
|
||||||
|
|||||||
Reference in New Issue
Block a user