react-redux学习笔记
2017.04.19
RuAn
 热度
℃
这里记录react-redux的一些关键点,并不是做为redux的介绍,自己备忘用。
参考资源
Redux是JavaScript应用程序的可预测状态容器。中文文档 You can use Redux together with React, or with any other view library.生态系统 :很好的redux资源
react-redux Sample Examples 实现容器组件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
const getVisibleTodos = (todos, filter ) => {
switch (filter) {
case 'SHOW_ALL' :
return todos
case 'SHOW_COMPLETED' :
return todos.filter(t => t.completed)
case 'SHOW_ACTIVE' :
return todos.filter(t => !t.completed)
}
}
const mapStateToProps = (state ) => {
return {
todos : getVisibleTodos(state.todos, state.visibilityFilter)
}
}
const mapDispatchToProps = (dispatch ) => {
return {
onTodoClick : (id ) => {
dispatch(toggleTodo(id))
}
}
}
import { connect } from 'react-redux'
const VisibleTodoList = connect(
mapStateToProps,
mapDispatchToProps
)(TodoList)
export default VisibleTodoList
bindActionCreators 包装action
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
export function inputChange (value ) {
return {
type : INPUT_CHANGED,
value
}
}
import * as todoActionCreators from './todoActionCreators'
import * as counterActionCreators from './counterActionCreators'
import { bindActionCreators } from 'redux'
function mapStateToProps (state ) {
return { todos : state.todos }
}
function mapDispatchToProps (dispatch ) {
return {
todoActions : bindActionCreators(todoActionCreators, dispatch),
counterActions : bindActionCreators(counterActionCreators, dispatch)
}
}
function mapDispatchToProps (dispatch ) {
return {
actions : bindActionCreators(Object .assign({}, todoActionCreators, counterActionCreators), dispatch)
}
}
function mapDispatchToProps (dispatch ) {
return bindActionCreators(Object .assign({}, todoActionCreators, counterActionCreators), dispatch)
}
mergeProps 使用
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
import * as actionCreators from './actionCreators'
function mapStateToProps (state ) {
return { todos : state.todos }
}
function mergeProps (stateProps, dispatchProps, ownProps ) {
return Object .assign({}, ownProps, {
todos : stateProps.todos[ownProps.userId],
addTodo : (text ) => dispatchProps.addTodo(ownProps.userId, text)
})
}
export default connect(mapStateToProps, actionCreators, mergeProps)(TodoApp)
Store
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
import React from 'react'
import { render } from 'react-dom'
import { Provider } from 'react-redux'
import { createStore } from 'redux'
import todoApp from './reducers'
import App from './components/App'
let store = createStore(todoApp)
render(
<Provider store ={store} >
<App />
</Provider > ,
document .getElementById('root' )
)
异步Action
Middleware 在生态系统中,有几个比较常用的中间件。
react-thunk 处理异步Action
Redux Thunk middleware allows you to write action creators that return a function instead of an action. The thunk can be used to delay the dispatch of an action, or to dispatch only if a certain condition is met. The inner function receives the store methods dispatch and getState as parameters.
An action creator that returns a function to perform asynchronous dispatch:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
const INCREMENT_COUNTER = 'INCREMENT_COUNTER' ;
function increment ( ) {
return {
type : INCREMENT_COUNTER
};
}
function incrementAsync ( ) {
return dispatch => {
setTimeout(() => {
dispatch(increment());
}, 1000 );
};
}
An action creator that returns a function to perform conditional dispatch:
1
2
3
4
5
6
7
8
9
10
11
function incrementIfOdd ( ) {
return (dispatch, getState ) => {
const { counter } = getState();
if (counter % 2 === 0 ) {
return ;
}
dispatch(increment());
};
}
2.1.0版本后,还添加注入参数
1
2
3
4
5
6
7
8
9
10
11
const store = createStore(
reducer,
applyMiddleware(thunk.withExtraArgument(api))
)
function fetchUser (id ) {
return (dispatch, getState, api ) => {
}
}
redux-promise 1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
import { isFSA } from 'flux-standard-action' ;
function isPromise (val ) {
return val && typeof val.then === 'function' ;
}
export default function promiseMiddleware ({ dispatch } ) {
return next => action => {
if (!isFSA(action)) {
return isPromise(action)
? action.then(dispatch)
: next(action);
}
return isPromise(action.payload)
? action.payload.then(
result => dispatch({ ...action, payload : result }),
error => {
dispatch({ ...action, payload : error, error : true });
return Promise .reject(error);
}
)
: next(action);
};
}
通过中间件处理reducer中的promise payload.
1
2
3
4
5
6
7
8
9
10
11
12
13
const foo = () => ({
type : 'FOO' ,
payload : new Promise ()
});
const foo = () => ({
type : 'FOO' ,
payload : {
promise : new Promise ()
}
});
ducks-modular-redux ducks modular主要是吧reducer封装起来,在component中调用无需写过多type等参数,只需调用方法。
例子:1
2
3
4
5
6
7
8
9
10
11
12
13
function mapDispatchToProps (dispatch ) {
return {
inputChange : (value ) => dispatch(inputChange(value)),
inputSubmit : () => dispatch(inputSubmit()),
deleteListItem : (i ) => dispatch(deleteListItem(i)),
listItemClick : (i ) => dispatch(listItemClick(i))
};
}
export default connect(
mapStateToProps,
mapDispatchToProps
)(ToDoApp);
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
import React from 'react' ;
import List from './List' ;
import Input from './Input' ;
class ToDoApp extends React .Component {
onInputChange = (event ) => {
this .props.inputChange(event.target.value);
};
onInputSubmit = (event ) => {
event.preventDefault();
this .props.inputSubmit();
};
onListItemClick = (i ) => {
this .props.listItemClick(i)
};
deleteListItem = (i ) => {
this .props.deleteListItem(i)
};
render(){
console .log(this .props)
return (
<div className="row">
<div className="col-md-8 col-md-offset-2">
<div className="panel panel-default">
<div className="panel-body">
<h1>My To Do App</h1>
<hr/>
<List
onClick={this.onListItemClick}
listItems={this.props.toDoApp.list}
deleteListItem={this.deleteListItem}
/>
<Input
value={this.props.toDoApp.newToDo}
onChange={this.onInputChange}
onSubmit={this.onInputSubmit}
/>
</div>
</div>
</div>
</div>
);
}
}
export default ToDoApp;
createActionDispathchers example
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
* Creates a function which creates same-named action dispatchers from an object
* whose function properties are action creators. Any non-functions in the actionCreators
* object are ignored.
*/
var createActionDispatchers = actionCreators => dispatch =>
Object .keys(actionCreators).reduce((actionDispatchers, name ) => {
var actionCreator = actionCreators[name];
if (typeof actionCreator == 'function' ) {
actionDispatchers[name] = (...args ) => dispatch(actionCreator(...args));
}
return actionDispatchers;
}, {})
var actionCreators = require ('./ducks/widgets' );
var mapStateToProps = state => state.widgets;
var mapDispatchToProps = createActionDispatchers(actionCreators);
var MyComponent = React.createClass({ });
module .exports = connect(mapStateToProps , mapDispatchToProps)(MyComponent);