Skip to content

Commit b3750e4

Browse files
committed
Convert App to a function component.
1 parent 3493b3b commit b3750e4

File tree

1 file changed

+42
-56
lines changed

1 file changed

+42
-56
lines changed

client/modules/App/App.jsx

Lines changed: 42 additions & 56 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
import PropTypes from 'prop-types';
2-
import React from 'react';
3-
import { connect } from 'react-redux';
2+
import React, { useEffect, useRef, useState } from 'react';
3+
import { useDispatch, useSelector } from 'react-redux';
44
import getConfig from '../../utils/getConfig';
55
import DevTools from './components/DevTools';
66
import { setPreviousPath } from '../IDE/actions/ide';
@@ -14,51 +14,50 @@ function hideCookieConsent(pathname) {
1414
return false;
1515
}
1616

17-
class App extends React.Component {
18-
constructor(props, context) {
19-
super(props, context);
20-
this.state = { isMounted: false };
21-
}
17+
// TODO: get location from `useLocation` after upgrading react-router to v5.
18+
const App = ({ children, location }) => {
19+
const dispatch = useDispatch();
2220

23-
componentDidMount() {
24-
this.setState({ isMounted: true }); // eslint-disable-line react/no-did-mount-set-state
25-
document.body.className = this.props.theme;
26-
}
21+
const theme = useSelector((state) => state.preferences.theme);
22+
useEffect(() => {
23+
document.body.className = theme;
24+
}, [theme]);
2725

28-
componentWillReceiveProps(nextProps) {
29-
const locationWillChange = nextProps.location !== this.props.location;
30-
const shouldSkipRemembering =
31-
nextProps.location.state &&
32-
nextProps.location.state.skipSavingPath === true;
26+
// TODO: this is only needed for the initial load and would be better handled elsewhere - Linda
27+
const language = useSelector((state) => state.preferences.language);
28+
useEffect(() => {
29+
dispatch(setLanguage(language, { persistPreference: false }));
30+
}, [language]);
3331

34-
if (locationWillChange && !shouldSkipRemembering) {
35-
this.props.setPreviousPath(this.props.location.pathname);
36-
}
32+
// TODO: do we actually need this? - Linda
33+
const [isMounted, setIsMounted] = useState(false);
34+
useEffect(() => setIsMounted(true), []);
3735

38-
if (this.props.language !== nextProps.language) {
39-
this.props.setLanguage(nextProps.language, { persistPreference: false });
40-
}
41-
}
36+
const previousLocationRef = useRef(location);
37+
useEffect(() => {
38+
const prevLocation = previousLocationRef.current;
39+
const locationChanged =
40+
prevLocation && prevLocation.pathname !== location.pathname;
41+
const shouldSkipRemembering = location.state?.skipSavingPath === true;
4242

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

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

6362
App.propTypes = {
6463
children: PropTypes.element,
@@ -67,24 +66,11 @@ App.propTypes = {
6766
state: PropTypes.shape({
6867
skipSavingPath: PropTypes.bool
6968
})
70-
}).isRequired,
71-
setPreviousPath: PropTypes.func.isRequired,
72-
setLanguage: PropTypes.func.isRequired,
73-
language: PropTypes.string,
74-
theme: PropTypes.string
69+
}).isRequired
7570
};
7671

7772
App.defaultProps = {
78-
children: null,
79-
language: null,
80-
theme: 'light'
73+
children: null
8174
};
8275

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

0 commit comments

Comments
 (0)