11import 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' ;
44import getConfig from '../../utils/getConfig' ;
55import DevTools from './components/DevTools' ;
66import { 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
6362App . 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
7772App . 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