Skip to content

Commit f21b847

Browse files
authored
Merge pull request #2308 from lindapaiste/refactor/app
Convert `App` to a function component.
2 parents 6f59d5c + dcdeb12 commit f21b847

File tree

1 file changed

+43
-63
lines changed

1 file changed

+43
-63
lines changed

client/modules/App/App.jsx

Lines changed: 43 additions & 63 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,7 @@
11
import PropTypes from 'prop-types';
2-
import React from 'react';
3-
import { connect } from 'react-redux';
4-
import { withRouter } from 'react-router-dom';
2+
import React, { useEffect, useRef, useState } from 'react';
3+
import { useDispatch, useSelector } from 'react-redux';
4+
import { useLocation } from 'react-router-dom';
55
import getConfig from '../../utils/getConfig';
66
import DevTools from './components/DevTools';
77
import { setPreviousPath } from '../IDE/actions/ide';
@@ -15,77 +15,57 @@ function hideCookieConsent(pathname) {
1515
return false;
1616
}
1717

18-
class App extends React.Component {
19-
constructor(props, context) {
20-
super(props, context);
21-
this.state = { isMounted: false };
22-
}
18+
const App = ({ children }) => {
19+
const dispatch = useDispatch();
2320

24-
componentDidMount() {
25-
this.setState({ isMounted: true }); // eslint-disable-line react/no-did-mount-set-state
26-
document.body.className = this.props.theme;
27-
}
21+
const location = useLocation();
2822

29-
componentWillReceiveProps(nextProps) {
30-
const locationWillChange = nextProps.location !== this.props.location;
31-
const shouldSkipRemembering =
32-
nextProps.location.state &&
33-
nextProps.location.state.skipSavingPath === true;
23+
const theme = useSelector((state) => state.preferences.theme);
24+
useEffect(() => {
25+
document.body.className = theme;
26+
}, [theme]);
3427

35-
if (locationWillChange && !shouldSkipRemembering) {
36-
this.props.setPreviousPath(this.props.location.pathname);
37-
}
28+
// TODO: this is only needed for the initial load and would be better handled elsewhere - Linda
29+
const language = useSelector((state) => state.preferences.language);
30+
useEffect(() => {
31+
dispatch(setLanguage(language, { persistPreference: false }));
32+
}, [language]);
3833

39-
if (this.props.language !== nextProps.language) {
40-
this.props.setLanguage(nextProps.language, { persistPreference: false });
41-
}
42-
}
34+
// TODO: do we actually need this? - Linda
35+
const [isMounted, setIsMounted] = useState(false);
36+
useEffect(() => setIsMounted(true), []);
37+
38+
const previousLocationRef = useRef(location);
39+
useEffect(() => {
40+
const prevLocation = previousLocationRef.current;
41+
const locationChanged = prevLocation && prevLocation !== location;
42+
const shouldSkipRemembering = location.state?.skipSavingPath === true;
4343

44-
componentDidUpdate(prevProps) {
45-
if (this.props.theme !== prevProps.theme) {
46-
document.body.className = this.props.theme;
44+
if (locationChanged && !shouldSkipRemembering) {
45+
dispatch(setPreviousPath(prevLocation.pathname));
4746
}
48-
}
47+
previousLocationRef.current = location;
48+
}, [location]);
4949

50-
render() {
51-
const hide = hideCookieConsent(this.props.location.pathname);
52-
return (
53-
<div className="app">
54-
<CookieConsent hide={hide} />
55-
{this.state.isMounted &&
56-
!window.devToolsExtension &&
57-
getConfig('NODE_ENV') === 'development' && <DevTools />}
58-
{this.props.children}
59-
</div>
60-
);
61-
}
62-
}
50+
const hide = hideCookieConsent(location.pathname);
51+
52+
return (
53+
<div className="app">
54+
<CookieConsent hide={hide} />
55+
{isMounted &&
56+
!window.devToolsExtension &&
57+
getConfig('NODE_ENV') === 'development' && <DevTools />}
58+
{children}
59+
</div>
60+
);
61+
};
6362

6463
App.propTypes = {
65-
children: PropTypes.element,
66-
location: PropTypes.shape({
67-
pathname: PropTypes.string,
68-
state: PropTypes.shape({
69-
skipSavingPath: PropTypes.bool
70-
})
71-
}).isRequired,
72-
setPreviousPath: PropTypes.func.isRequired,
73-
setLanguage: PropTypes.func.isRequired,
74-
language: PropTypes.string,
75-
theme: PropTypes.string
64+
children: PropTypes.element
7665
};
7766

7867
App.defaultProps = {
79-
children: null,
80-
language: null,
81-
theme: 'light'
68+
children: null
8269
};
8370

84-
const mapStateToProps = (state) => ({
85-
theme: state.preferences.theme,
86-
language: state.preferences.language
87-
});
88-
89-
const mapDispatchToProps = { setPreviousPath, setLanguage };
90-
91-
export default withRouter(connect(mapStateToProps, mapDispatchToProps)(App));
71+
export default App;

0 commit comments

Comments
 (0)