星期三, 10月 05, 2016
React Component shouldComponentUpdate 實作
最近朋友遇到一個有趣的React問題,可能頁面上有個值,一秒鐘會有幾萬筆資料進來,但是如果要一直更新畫面,效果不好。
這邊我推薦使用shouldComponentUpdate 來阻擋這種一秒鐘幾十萬資料變動的畫面呈現議題。
範例程式碼如下
http://jsbin.com/lilubaj
1. ParentComponent每1ms變動一次數值給ChildComponent(this.state.count)。
2. ChildComponent會在畫面上呈現(this.props.count)。
3. shouldComponentUpdate 有個timer設置每1秒才會允許畫面更新一次。
4. componentWillReceiveProps 原本的資料還是每1ms都會更新(資料流是正確的)。
星期二, 7月 12, 2016
Redux middleware 筆記
使用redux middleware完成非同步呼叫
我們團隊在開始使用action->dispatch->reducer其實進入蠻快的
但是當進入到非同步的時候就卡關了
因為要在action creator要處理非同步,如果不使用middleware
我們可能會在action creator
export function addTodo(text) {
setTimeout(function () {
return { type: ADD_TODO, text }
},3000)
}
但是reducer會跟你說錯,因為回來的東西並不是action而是一個function,reducer無法處理,這時候就需要middleware處理了。
我們大概可以把 middleware當作redux流程中的一部分。
action->dispatcher->customized async middleware-> reducer 產生新的state。
============async call sample===========
var Promise = require('bluebird');
var Superagent = require('superagent');
function asyncMiddleware(){
return function store(store){
return function next(next){ //next middleware
return function actionHandle(action){
if (typeof action.ASYNC_CALL !== 'undefined') {
return next(action);
//如果action沒有關鍵字ASYNC_CALL,則直接走下一個middleware
}
var type = action.type;
return new Promise(function promiseHandle(resolve, reject){
//這邊我們使用bluebird的Promise來達成promise
function responseCallback(responseError, response){
//some code error handle or resolve promise
next({
type: type,
response: response
});
resolve(response);
}
//do ajax call
//這邊我們是使用superagent 來get/put/post/delete
Superagent.get(target).query(params).set(header).end(responseCallback);
});
}
}
}
}
=========action creator=================
而我們的action creator就很簡單了
例如下面這個是非同步呼叫載入個人資料
export const LOADED_PROFILE = 'LOADED_PROFILE';
export function loadProfile(params) {
return {
'ASYNC_CALL': { //有此關鍵字 middleware會走 ajax call
type: LOADED_PROFILE,
method: 'get',
target: '/profile/:pid',
params: params
}
};
};
=========component/container===========
import { loadProfile } from 'actions/profile';
class Profile extends Component {
componentDidMount() {
var params = {};//get/post的參數
this.props.loadProfile(params).then(function(result) {
//do something
});
}
}
var mapDispatchToProps = { loadProfile };
export default connect(mapStateToProps, mapDispatchToProps)(Profile);
=========小結=====================
透過這種方式,團隊成員在使用redux流程都會很一致的
action->(middlewares)->reducer->store
不用知道middlewares的細節就可以完成開發
(不過當然我都有解釋給他們聽原理)
=========附註======================
我們是從redux-thunk的source code理解實作方法的
https://github.com/gaearon/redux-thunk/blob/master/src/index.js
只有短短10多行程式碼
redux middleware的說明官方文件跟有人從頭跑過一次redux middleware的中文說明
http://redux.js.org/docs/advanced/Middleware.html
http://huli.logdown.com/posts/294284-javascript-redux-middleware-details-tutorial
星期日, 7月 10, 2016
React-Redux 筆記
react-redux其實概念我整理如下
=================Store層========================
rootStore管理整個React App的資料(我們先稱他為root)
ex:
action會定義我們的操作
ex:
=================Reducer定義層========================
reducer負責處理 action來的狀態變化
所以跟rootStore類似,我們會拆幾個reducer來處理
=================Component/Container(view)定義層=========
React-redux的元件跟react元件最大的不同就是有引入react-redux的connect()方法。
要熟悉react-redux 對他提供的connect一定要熟悉
第一個連接的是這個component的mapStateToPros 這個function
第二個是這個component會發出的action,官方是稱他為 mapDispatchToProps
做了上述兩個動作,這個react component就在redux資料流當中了
this.props.profile就有相對應的資料
this.props.addProfileData 也可以dispatch透過reducer,更新rootStore的資料。
第三個參數 mergeProps 第四個為option
後兩個比較少用,避免混淆觀念,我這篇先跳過,有興趣可以參閱官方API
https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-apdispatchtoprops-mergeprops-options
=================後序========================
以上是最基本的redux在react的應用流程,
之後還有要跟大家說的,如果redux會使用到非同步呼叫或是其他功能需求(ex logger),
我們是使用redux middleware來完成。
- 有個中央控管的rootStore
- 元件把自己需要的rootStore map回去變成自己的props
- 元件可以發出action去變動rootStore 進而更新自己的畫面
=================Store層========================
rootStore管理整個React App的資料(我們先稱他為root)
ex:
{ root :
profile:{...profileData},
friend: {...friendData},
privacy: {...privacy}
}
=================Action定義層========================action會定義我們的操作
ex:
const ADD_PROFILE_DATA = 'ADD_PROFILE_DATA';
addProfileData(data) {
{
type: ADD_PROFILE_DATA,// for reducer使用
data:data //這個action會變動的資訊
}
}
=================Reducer定義層========================
reducer負責處理 action來的狀態變化
所以跟rootStore類似,我們會拆幾個reducer來處理
rootReducer= combineReducers({
profileReducer,
friendReducer,
privacyReducer
});
const profileReducer = function (state, action ) {
switch(action.type) //action所定義的type
case 'ADD_PROFILE_DATA'
state.profile = action.data
return state; //這兩個的意義 (state, action) => new state
default:
return state;//沒定義的action不變動state
}
=================Component/Container(view)定義層=========
React-redux的元件跟react元件最大的不同就是有引入react-redux的connect()方法。
import { connect } from 'react-redux';
import {addProfileData} from 'action/profile';
class Profile extends Component {
//react lifecycle method, render methor
}
mapStateToProps (state) {
profile: state.profile
//我的Profile只需要profile的資料
//就map rootStore的 profile變成自己的props
//如果今天有其他的action變動到rootStore profile的資料
//Profile也會跟著更新狀態
}
export default connect(
mapStateToProps, { addProfileData } ,{/*mergeProps*/},{/*option*/})( Profile );
要熟悉react-redux 對他提供的connect一定要熟悉
第一個連接的是這個component的mapStateToPros 這個function
第二個是這個component會發出的action,官方是稱他為 mapDispatchToProps
做了上述兩個動作,這個react component就在redux資料流當中了
this.props.profile就有相對應的資料
this.props.addProfileData 也可以dispatch透過reducer,更新rootStore的資料。
第三個參數 mergeProps 第四個為option
後兩個比較少用,避免混淆觀念,我這篇先跳過,有興趣可以參閱官方API
https://github.com/reactjs/react-redux/blob/master/docs/api.md#connectmapstatetoprops-apdispatchtoprops-mergeprops-options
=================後序========================
以上是最基本的redux在react的應用流程,
之後還有要跟大家說的,如果redux會使用到非同步呼叫或是其他功能需求(ex logger),
我們是使用redux middleware來完成。
訂閱:
文章 (Atom)