Skip to content

Commit

Permalink
s8 - Add redux into reactjs app
Browse files Browse the repository at this point in the history
  • Loading branch information
paulnguyen-mn committed Apr 21, 2020
1 parent 09694b2 commit 4099008
Show file tree
Hide file tree
Showing 13 changed files with 362 additions and 28 deletions.
17 changes: 17 additions & 0 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 2 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -6,10 +6,12 @@
"@testing-library/jest-dom": "^4.2.4",
"@testing-library/react": "^9.3.2",
"@testing-library/user-event": "^7.1.2",
"classnames": "^2.2.6",
"prop-types": "^15.7.2",
"query-string": "^6.12.0",
"react": "^16.13.1",
"react-dom": "^16.13.1",
"react-redux": "^7.2.0",
"react-router-dom": "^5.1.2",
"react-scripts": "3.4.1",
"redux": "^4.0.5"
Expand Down
22 changes: 22 additions & 0 deletions s8-react-redux.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,22 @@
# S8 - React Redux

React Context API
- Provider: 1
- Consumers: nhiều

Redux: lib - npm package: redux
- store
- action: object {type: '', payload: ''}
- reducer


Multiple Reducers --> combined reducers
Add todo list reducer


react
react-dom
redux

react-redux: install package
HOC: Higher Order Component
85 changes: 84 additions & 1 deletion src/App.js
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
import React, { PureComponent } from 'react';
import { BrowserRouter, Route, Switch, NavLink, Link, Redirect } from 'react-router-dom';
import PropTypes from 'prop-types';
import classnames from 'classnames';

import './App.scss';
import AboutPage from './containers/AboutPage';
Expand All @@ -10,6 +12,10 @@ import ProductListPage from './containers/ProductListPage';
import AddEditProductPage from './containers/AddEditProductPage';
import ProductDetailPage from './containers/ProductDetailPage';
import GlobalContext from './contexts/globalContext';
import { connect } from 'react-redux';
import { bindActionCreators } from 'redux';
import { increaseCounter, decreaseCounter } from './actions/counter';
import { addHero, setActiveHero } from './actions/hero';

class App extends PureComponent {
constructor(props) {
Expand Down Expand Up @@ -47,11 +53,62 @@ class App extends PureComponent {
}))
}

handleIncreaseClick = () => {
this.props.increaseCounter();
}

handleDecreaseClick = () => {
this.props.decreaseCounter();
}

handleAddHeroClick = () => {
const randomId = 1000 + Math.trunc(Math.random() * 9000);
const newHero = {
id: randomId,
name: 'Thor',
power: randomId,
};
this.props.addHero(newHero);
}

handleHeroClick = (hero) => {
this.props.setActiveHero(hero);
}

render() {
const { heroList, activeHero, count } = this.props;
console.log('REDUX State: ', { heroList, activeHero, count });

const { initialState } = this.state;


return (
<div className="App">
<h1>COUNTER: {count}</h1>
<button onClick={this.handleDecreaseClick}>Decrease</button>
<button onClick={this.handleIncreaseClick}>Increase</button>
<button onClick={this.handleAddHeroClick}>Add hero</button>

<ul>
{heroList.map(hero => {
const heroClasses = classnames({
'hero-item': true,
active: hero.id === activeHero.id,
});

return (
<li
key={hero.id}
className={heroClasses}
onClick={() => this.handleHeroClick(hero)}
>
{hero.name} - {hero.power}
</li>
)
})}
</ul>


<button onClick={this.handleClick}>Change context value</button>

<GlobalContext.Provider value={initialState}>
Expand All @@ -77,7 +134,33 @@ class App extends PureComponent {
}
}

export default App;
App.propTypes = {
heroList: PropTypes.array.isRequired,
activeHero: PropTypes.object.isRequired,
count: PropTypes.number.isRequired,

increaseCounter: PropTypes.func.isRequired,
decreaseCounter: PropTypes.func.isRequired,
addHero: PropTypes.func.isRequired,
setActiveHero: PropTypes.func.isRequired,
}

const mapStateToProps = state => ({
heroList: state.hero.list,
activeHero: state.hero.activeHero,
count: state.counter,
})

const mapDispatchToProps = dispatch => {
return bindActionCreators({
increaseCounter,
decreaseCounter,
addHero,
setActiveHero,
}, dispatch);
}

export default connect(mapStateToProps, mapDispatchToProps)(App);


// HomePage
Expand Down
4 changes: 4 additions & 0 deletions src/App.scss
Original file line number Diff line number Diff line change
Expand Up @@ -57,3 +57,7 @@
}
}
}

.hero-item.active {
color: deeppink;
}
7 changes: 7 additions & 0 deletions src/actions/actionType.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@

// Counter
export const INCREMENT = 'increment'
export const DECREMENT = 'decrement'

// Hero
// export
13 changes: 13 additions & 0 deletions src/actions/counter.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,13 @@
import { INCREMENT, DECREMENT } from "./actionType"

export const increaseCounter = () => {
return {
type: INCREMENT,
}
}

export const decreaseCounter = () => {
return {
type: DECREMENT,
}
}
26 changes: 26 additions & 0 deletions src/actions/hero.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@

export const addHero = (hero) => {
return {
type: 'ADD_HERO',
payload: hero,
}
}

export const removeHero = (heroId) => {
return {
type: 'REMOVE_HERO',
payload: heroId,
}
}

export const setActiveHero = (hero) => {
return {
type: 'SET_ACTIVE_HERO',
payload: hero,
}
}

export const getHeroList = () => {
// Call API
// Update redux store by dispatching an action
}
Loading

0 comments on commit 4099008

Please sign in to comment.