Chia Yu Pai @ Rytass
HTML
CSS
Javascript
Structure
Face
Interactive
Finger
Palm
HTML
structure
Black
White
CSS
face
Javascript
interactive
feature
Model View Controller
View
# | name | feature |
---|---|---|
1 | mi-home | cheap |
2 | Nest | beautiful |
# | product | score |
---|---|---|
1 | 1 | 4 |
2 | 1 | 3 |
3 | 2 | 5 |
Model
Controller
Model
View
Controller
Model
React
React Router
Redux
View
React
class MemberList extends Component {
componentWillMount() {
this.props.fetchMembers();
}
render() {
return (
<div style={styles.wrapper}>
<MemberListFilter />
<MemberListTable />
</div>
);
}
}
Handling Structure
View
React
class MemberListFilter extends Component {
contructure(props) {
super(props);
this.state = {
filterTerm: '',
};
}
render() {
const {
filterTerm,
} = this.state;
const {
submitFilter,
} = this.props;
return (
<div style={styles.wrapper}>
<input
type="text"
placeholder="Search"
value={filterTerm}
onChange={e => this.setState({ filterTerm: e.target.value })} />
<button type="button" onClick={submitFilter} />
</div>
);
}
}
MemberListFilter.propTypes = {
submitFilter: PropTypes.func,
};
Self Model and Controller
React Component Model
Props
State
Get from parent node
Should not change
Component Scope
Only self or children used
Context
Influence nest children
Environment like
React Component Lifecycle
Mount
Update
Unmount
constructor() - state initial
componentWillMount()
componentWillReceiveProps()
componentWillUpdate()
shouldComponentUpdate()
componentDidUpdate()
componentWillUnmount()
DOM Mounted
Controller
React Router
<Provider store={store}>
<Router history={history}>
<Route path="/" component={MainBoard}>
<Route path="sewers">
<Route path="checkers">
<IndexRoute component={CheckerPage} />
</Route>
<Route path="constructions">
<Route path="create" component={RainConstructionCreatePage} />
<Route path=":constructionId" component={RainConstructionDetailPage} />
<IndexRoute component={RainConstructionListPage} />
</Route>
<Route path="facilities" component={RainFacilitiesManagementPage} />
<Route path="tenders" component={RainTenderManagePage} />
<IndexRoute component={RainTenderManagePage} />
</Route>
</Route>
</Router>
</Provider>
Site Router
Single Page Application
Model
Redux
Data from Server
Actions
Reducers
User Interface
State Machine
Change Watch
Fetch Data
Interactive
Action Creator
Dispatch Action
Dispatch Action
Replace State
import { API_REQUEST } from 'redux-middleware-fetch';
export const LOGIN_SUCCESS = Symbol('LOGIN_SUCCESS');
export const LOGIN_FAILED = Symbol('LOGIN_FAILED');
export const LOGIN_REQUEST = Symbol('LOGIN_REQUEST');
export function login(account, password) {
return {
[API_REQUEST]: {
types: [
LOGIN_SUCCESS,
LOGIN_FAILED,
LOGIN_REQUEST,
],
method: 'POST',
entrypoint: '/auth/login',
json: true,
body: {
account,
password,
},
},
};
}
Redux Action
export const AUTH_LOGED_OUT = Symbol('AUTH_LOGED_OUT');
export function logout() {
return {
type: AUTH_LOGED_OUT,
};
}
Fetch from server
Direct dispatch
import {
AUTH_LOGINED,
AUTH_LOGED_OUT,
} from '../actions/Auth.js';
export default (state = {
id: null,
accessToken: null,
name: 'Guest',
}, action) => {
switch (action.type) {
case AUTH_LOGED_OUT:
return {
...state,
id: null,
accessToken: null,
};
case AUTH_LOGINED:
return {
...state,
id: action.id,
accessToken: action.accessToken,
};
default:
return state;
}
};
Redux Reducer
Observer pattern
Immutable
import { combineReducers } from 'redux';
import Auth from './Auth.js';
import Member from './Member.js';
export default combineReducers({
Auth,
Member,
});
Combined