[Redux] react-redux API 筆記
react-redux documentation @ github
connect API
connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options]);
在 Redux 中可以透過 connect
將傳入該 components 的 states 和 actions 進行篩選或初步處理,這個方法不會改變你原本的 components,而是回傳一個加料 後新的 components 給你。
mapStateToProps:使用 connect 來取得 Redux 中的 states
mapStateToProps @ react-redux
// ownProps 指的是該 component 本身所擁有的 props
// state 則是指在 Redux store 中的所有資料
function mapStateToProps(state, [ownProps]) {
return {
// 在該 components 中會用到的資料
};
}
- 當在
connect
中代入這個參數後,新的元件會 訂閱 Redux store 的更新,也就是說每次只要 store 有更新,mapSateToProps
都會被呼叫到。 mapStateToProps
回傳的內容必需是一個物件,它會合併到該元件的props
屬性中。- 如果你不希望訂閱 Redux 中 store 的更新,那麼可以把這個參數代入
null
或undefined
。 - 在
mapStateToProps
中第一個參數會是整個 Redux store 中的 state,可以從中篩選希望進到此元件的資料作為props
,因此它也常被稱作 selector。
程式範例
// @/containers/post_index.js
import React from 'react';
import { connect } from 'react-redux';
class PostIndex extends React.Component {
/* 原本在 Redux 中的 state.posts 可以透過 this.props.posts 取得 */
console.log(this.props.posts);
render() {
return <h1>I'm a Redux container.</h1>;
}
}
/* 不篩選任何資料,全部 Redux 的 states 都進來此元件 */
// const mapStateToProps = state => state;
const mapStateToProps = (state, ownProps) => {
/* 這裡 return 的內容將可以在 this.props 中使用 */
return {
posts: state.posts // 這裡只傳入 Redux states 中的 posts 資料進來此元件
}
}
connect(mapStateToProps)(PostIndex);
mapDispatchToProps:使用 connect 來 dispatch actions
mapDispatchToProps @ react-redux
[mapDispatchToProps(dispatch, [ownProps]): dispatchProps] (Object or Function)
代入函式:針對 action generator 進行篩選或前置處理
// @/containers/post_index.js
import React from 'react';
import { connect } from 'react-redux';
import { fetchPosts } from '@/actions';
class PostIndex extends React.Component {
render() {
/* 不需要 this.props.dispatch(fetchPosts()) */
this.props.fetchPosts();
return <h1>I'm a Redux container.</h1>;
}
}
const mapDispatchToProps = (dispatch, ownProps) => {
/* 這裡 return 的內容將可以在 this.props 中使用 */
return {
fetchPosts: () => dispatch(fetchPosts()),
};
};
connect(mapStateToProps, mapDispatchToProps)(PostIndex);
bindActionCreators
如果想要更簡便的寫法,也可以在 mapDispatchToProps
中使用 bindActionCreators
:
import { bindActionCreators } from 'redux';
import { fetchPosts } from '@/actions';
const mapDispatchToProps = (dispatch, ownProps) => {
/* 這裡 return 的內容將可以在 this.props 中使用 */
return bindActionCreators({ fetchPosts }, dispatch);
};
建議:如果單純只要 dispatch action
the "object shorthand" form of
mapDispatch
@ react-redux
如果單純要把 action generators 放到 this.props
中可以直接使用該 action:
// @/containers/post_index.js
import React from 'react';
import { connect } from 'react-redux';
import { fetchPosts } from '@/actions';
class PostIndex extends React.Component {
render() {
/* 直接使用即可,不需要 this.props.dispatch(fetchPosts()) */
this.props.fetchPosts();
return <h1>I'm a Redux container.</h1>;
}
}
/* 單純只是要 dispatch action 的話,可以直接代入物件 */
connect(mapStateToProps, { fetchPosts })(PostIndex);
We recommend always using the “object shorthand” form of
mapDispatch
, unless you have a specific reason to customize the dispatching behavior. @ StackOverflow
範例影片
不使用 connect API
不使用 connect 取得 Redux 中的 states
如果沒有使用 connect
想要 取得 Redux 中的 states,需要先手動透過 props
把建立的 store 傳入元件中:
// @/index.js
import React from 'react';
import ReactDOM from 'react-dom';
import { Provider } from 'react-redux';
import { createStore } from 'redux';
import rootReducers from '@/reducers';
import PostIndex from '@/containers/post_index';
const store = createStore(rootReducers);
const root = ReactDOM.createRoot(document.getElementById('app'));
root.render(
<Provider>
{/* 把建立好的 store 代入元件中 */}
<PostIndex store={store} />
</Provider>
);
接著即可在元件中使用 this.props.store.getState()
取得 Redux 的 states:
// @/containers/post_index.js
import React from 'react';
class PostIndex extends React.Component {
render() {
/* 不使用 connect 取得 Redux 的 states */
this.props.store.getState();
return <h1>I am a Redux container.</h1>;
}
}
不使用 connect 來 dispatch actions
如果沒有使用 connect
想要直接在 containers 中 dispatch action,因為在 this.props
中已經帶有 dispatch
方法,因此只需把撰寫好的 action generators 載入再**發送(dispatch)**即可。
// @/actions/index.js
export const fetchPost = (id) => ({
type: 'FETCH_POST',
payload: id,
});