11import 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' ;
55import getConfig from '../../utils/getConfig' ;
66import DevTools from './components/DevTools' ;
77import { 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
6463App . 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
7867App . 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