For setting up React with I18n refer to my previous article here if you have already set up React with I18n then let’s proceed
Note: this article will not cover the theoretical part of store management using Redux, only how to set it up.
- Clone the boilerplate :
git clone https://github.com/abnaceur/reactMultiLang.git
2. Install packages
npm i -save redux-thunk redux-promise redux-devtools-extension redux react-redux react-router-redux
3. Create the store folder structure as follow
src
├── App.css
├── App.js
├── App.test.js
├── components
├── helpers
│ └── i18n.js
├── index.css
├── index.js
├── logo.svg
├── serviceWorker.js
├── setupTests.js
└── store
├── actions
│ └── ActionType.js
├── configureStore.js
└── reducers
4. Create store configuration in store/configureStore.js
import { combineReducers } from 'redux';
import { routerReducer } from "react-router-redux";
const reducers = combineReducers({
router: routerReducer,
});
export default reducers;
5. Wrap <App/> component in index.js within redux provider
import './helpers/i18n';
import React from 'react';
import ReactDOM from 'react-dom';
import './index.css';
import App from './App';
import * as serviceWorker from './serviceWorker';
import { Provider } from "react-redux";
import { routerMiddleware } from "react-router-redux";
import { createStore, applyMiddleware } from "redux";
import thunk from "redux-thunk";
import { composeWithDevTools } from 'redux-devtools-extension';
import promiseMiddleware from 'redux-promise';
import reducers from './store/configureStore';
const createHistory = require("history").createBrowserHistory;
const history = createHistory();
const middleware = routerMiddleware(history);
const store = createStore(reducers, composeWithDevTools(applyMiddleware(middleware, promiseMiddleware, thunk)));
ReactDOM.render(
<Provider store={store}>
<App />
</Provider>, document.getElementById('root'));
serviceWorker.unregister();
6. Start the server and check chrome devTools
npm start
7. Let’s test our store by creating a new action
a. Create the action type in store/action/ActionType.js
export const GET_DATA = 'GET_DATA';
b. In src/store/action/ create a new action GetDataAction/GetDataAction.js
import {
GET_DATA,
} from '../ActionType';
export function getData() {
let data = {
id: 1,
username: "John Doe",
age: "42",
position: "Software engineer"
};
return function (dispatch) {
dispatch({
type: GET_DATA,
payload: data
})
}
}
c. Create the action’s reducer in store/reducers/GetDataReducer/GetDataReducer.js
import {
GET_DATA,
} from "../../actions/ActionType";
const initialState = {
getData: [],
};
export default function(state = initialState, action) {
switch (action.type) {
case GET_DATA:
return {
data: action.payload,
};
default:
return state;
}
}
d. Add the new reducer to the store configuration store/configureStore.js
import { combineReducers } from 'redux';
import { routerReducer } from "react-router-redux";
import getDataReducer from './reducers/GetDataReducer/GetDataReducer';
const reducers = combineReducers({
getDataReducer: getDataReducer,
router: routerReducer,
});
export default reducers;
Awesome everything is set up now let’s call our action from the <app /> component but first, we need to connect it to the store.
import React, { Suspense } from 'react';
import './App.css';
import { useTranslation } from 'react-i18next';
import { connect, useDispatch, useSelector } from "react-redux";
import { push } from "react-router-redux";
import { getData } from './store/actions/GetDataAction/GetDataAction';
function Page() {
const { t } = useTranslation();
return (
<div>
<h1>{t('home.mainTitle')}</h1>
<h3>{t('home.text')}</h3>
<p>{t('home.description')}</p>
</div>
)
}
function Header() {
const { i18n } = useTranslation();
const handleChange = (lang) => {
i18n.changeLanguage(lang);
}
return (
<div>
<button className="btn" onClick={e => { handleChange('en') }}>EN</button>
<button className="btn" onClick={e => { handleChange('fr') }}>FR</button>
</div>
)
}
function GetUserData() {
const dispatch = useDispatch();
return <div>
<button className="btn" onClick={e => { dispatch(getData()) }}>Get user data</button>
</div>
}
function App() {
return (
<Suspense fallback="Loading ..." >
<Header />
<div className="App">
<Page />
<GetUserData />
</div>
</Suspense>
);
}
const state = (state, ownProps = {}) => {
return {
getDataReducer: state.getDataReducer,
location: state.location,
}
}
const mapDispatchToProps = (dispatch, ownProps) => {
return {
navigateTo: (location) => {
dispatch(push(location));
},
}
};
export default connect(state, mapDispatchToProps)(App)
Once done let’s navigate to http://localhost:3000 in the browser and check redux devTools.
By clicking on the button “Get user data“ we dispatched the action getData.
Remember practice makes perfection, I hope you found this article helpful. Github source code here.