跳至主要内容

[Redux] react-redux API 筆記

react-redux documentation @ github

connect API

connect([mapStateToProps], [mapDispatchToProps], [mergeProps], [options]);

在 Redux 中可以透過 connect 將傳入該 components 的 statesactions 進行篩選初步處理,這個方法不會改變你原本的 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 的更新,那麼可以把這個參數代入 nullundefined
  • 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,
});

action generator 載入後使用 this.props.dispatch(action)

// @/containers/post_index.js

import React from 'react';
import fetchPost from '@/actions/';

class PostIndex extends React.Component {
render() {
/* 不使用 connect 使用 Redux 的 dispatch 發送 action */
this.props.dispatch(fetchPost());
return <h1>I am a Redux container.</h1>;
}
}

註:由於在 Redux 中元件的 props 預設就帶有 dispatch() 方法,因此需要先把 store 載入後,再透過 this.store.dispatch(action) 來發送 action。

查看更多使用範例

react-redux examples @ react-redux github