Skip to content

Commit e95fb8c

Browse files
committed
feat: use redux to select the language
1 parent c37f687 commit e95fb8c

File tree

12 files changed

+151
-42
lines changed

12 files changed

+151
-42
lines changed

package.json

Lines changed: 4 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -85,6 +85,7 @@
8585
"node-sass": "^4.12.0",
8686
"prettier": "^1.18.2",
8787
"react-docgen-typescript-loader": "^3.1.0",
88+
"redux-devtools-extension": "^2.13.8",
8889
"sass": "^1.22.7",
8990
"sass-loader": "^7.1.0",
9091
"semantic-release": "^15.13.18",
@@ -102,6 +103,8 @@
102103
"normalize.css": "^8.0.1",
103104
"phaser-ce": "2.13.2",
104105
"react": "^16.8.6",
105-
"react-dom": "^16.8.6"
106+
"react-dom": "^16.8.6",
107+
"react-redux": "^7.1.0",
108+
"redux": "^4.0.4"
106109
}
107110
}

src/app/App.tsx

Lines changed: 12 additions & 38 deletions
Original file line numberDiff line numberDiff line change
@@ -1,47 +1,21 @@
1-
import React, { Component } from 'react';
1+
import React from 'react';
2+
import { useSelector } from 'react-redux';
23

34
import { TheGame } from './the-game';
4-
import { Language, LanguageSelector } from './components';
5+
import { SelectLanguage } from './containers';
56
import { isEmpty } from 'lodash';
6-
import { i18nService, SupportedLocale } from '../i18n/I18nService';
7+
import { i18nService } from '../i18n/I18nService';
78
import './App.scss';
89

9-
type AppProps = {};
10+
export const App = () => {
11+
i18nService.init();
1012

11-
type AppState = {
12-
selectedLanguage: string;
13-
availableLanguages: Language[];
14-
};
15-
16-
export class App extends Component<AppProps, AppState> {
17-
constructor(props: AppProps) {
18-
super(props);
19-
20-
i18nService.init();
21-
22-
this.state = {
23-
selectedLanguage: '',
24-
availableLanguages: [{ code: 'en', name: 'English' }, { code: 'fr', name: 'Français' }],
25-
};
26-
}
13+
const selectedLanguage = useSelector(state => state.language.selectedLanguage);
2714

28-
setActiveLanguage(language: SupportedLocale) {
29-
this.setState({ ...this.state, selectedLanguage: language });
30-
return i18nService.setLanguage(language);
15+
let component = <SelectLanguage />;
16+
if (!isEmpty(selectedLanguage)) {
17+
component = <TheGame />;
3118
}
3219

33-
render() {
34-
let component = (
35-
<LanguageSelector
36-
languages={this.state.availableLanguages}
37-
setActiveLanguage={l => this.setActiveLanguage(l)}
38-
/>
39-
);
40-
41-
if (!isEmpty(this.state.selectedLanguage)) {
42-
component = <TheGame />;
43-
}
44-
45-
return component;
46-
}
47-
}
20+
return component;
21+
};

src/app/app.store.ts

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,5 @@
1+
import { createStore } from 'redux';
2+
import { composeWithDevTools } from 'redux-devtools-extension';
3+
import { reducers } from './reducers';
4+
5+
export const store = createStore(reducers, composeWithDevTools());

src/app/containers/index.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './select-language';
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
import { Dispatch } from 'redux';
2+
import { connect } from 'react-redux';
3+
4+
import { LanguageSelector } from '../../components';
5+
import { selectLanguage } from '../../reducers';
6+
import { i18nService, SupportedLocale } from '../../../i18n/I18nService';
7+
8+
const mapStateToProps = (state: any) => {
9+
return {
10+
languages: state.language.availableLanguages,
11+
};
12+
};
13+
14+
const mapDispatchToProps = (dispatch: Dispatch) => {
15+
return {
16+
setActiveLanguage: async (selectedLanguage: SupportedLocale) => {
17+
await i18nService.setLanguage(selectedLanguage);
18+
dispatch(selectLanguage(selectedLanguage));
19+
},
20+
};
21+
};
22+
23+
export const SelectLanguage = connect(
24+
mapStateToProps,
25+
mapDispatchToProps,
26+
)(LanguageSelector);
Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
export * from './SelectLanguage';

src/app/reducers/index.ts

Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
import { combineReducers } from 'redux';
2+
import { languageReducer } from './language.reducer';
3+
4+
export * from './language.action';
5+
export { LanguageState } from './language.reducer';
6+
7+
export const reducers = combineReducers({
8+
language: languageReducer,
9+
});
Lines changed: 17 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,17 @@
1+
import { SupportedLocale } from '../../i18n/I18nService';
2+
3+
export const SELECT_LANGUAGE = 'SELECT_LANGUAGE';
4+
5+
export type SelectLanguageAction = {
6+
type: typeof SELECT_LANGUAGE;
7+
payload: SupportedLocale;
8+
};
9+
10+
export type LanguageActionTypes = SelectLanguageAction;
11+
12+
export function selectLanguage(language: SupportedLocale): SelectLanguageAction {
13+
return {
14+
type: SELECT_LANGUAGE,
15+
payload: language,
16+
};
17+
}
Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,16 @@
1+
import { selectLanguage } from './language.action';
2+
import { languageReducer } from './language.reducer';
3+
4+
describe('Language reducer', () => {
5+
it('provides an initial state', () => {
6+
expect(languageReducer(undefined, {} as any)).toEqual({
7+
selectedLanguage: '',
8+
});
9+
});
10+
11+
it('set the languageReducer on SELECT_LANGUAGE', () => {
12+
expect(languageReducer(undefined, selectLanguage('fr'))).toEqual({
13+
selectedLanguage: 'fr',
14+
});
15+
});
16+
});
Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,25 @@
1+
import { LanguageActionTypes } from './language.action';
2+
import { Language } from '../components/language-selector';
3+
4+
export type LanguageState = {
5+
availableLanguages: Language[];
6+
selectedLanguage: string;
7+
};
8+
9+
const INITIAL_STATE: LanguageState = {
10+
availableLanguages: [{ code: 'en', name: 'English' }, { code: 'fr', name: 'Français' }],
11+
selectedLanguage: '',
12+
};
13+
14+
export const languageReducer = (state = INITIAL_STATE, action: LanguageActionTypes) => {
15+
switch (action.type) {
16+
case 'SELECT_LANGUAGE':
17+
return {
18+
...state,
19+
selectedLanguage: action.payload,
20+
};
21+
22+
default:
23+
return state;
24+
}
25+
};

0 commit comments

Comments
 (0)