redux从零开始入门笔记
为什么需要redux学过react的都知道,react用 Redux的基本概念什么是redux?这里非权威的解释:就是一个应用的state管理库,甚至可以说是前端数据库。更包括的是管理数据。 statestate是整个应用的数据,本质上是一个普通对象。 action数据state已经有了,那么我们是如何实现管理这些state中的数据的呢?那就是action,什么是action?按字面意思解释就是动作,也可以理解成,一个可能!改变state的动作包装。就这么简单。。。。 export function decrement() { return{ type:DECREMENT_COUNTER } } export function increment(){ return{ type:INCREMENT_COUNTER } } 那么,当action创建完成了之后呢,我们怎么触发这些action呢,这时我们是要利用 export function incrementIfOdd(){ return(dispatch,getState)=>{ const {counter} = getState(); if(counter%2==0) { return; } dispatch(increment()); } } export function incrementAsync() { return dispatch => { setTimeout(() => { dispatch(increment()); },1000); }; } 为了减少样板代码,我们使用单独的模块或文件来定义 action type 常量 export const INCREMENT_COUNTER = 'INCREMENT_COUNTER'; export const DECREMENT_COUNTER = 'DECREMENT_COUNTER'; 这么做不是必须的,在大型应用中把它们显式地定义成常量还是利大于弊的。 reducer既然这个可能改变state的动作已经包装好了,那么我们怎么去判断并且对state做相应的改变呢?对,这就是reducer干的事情了。 import {INCREMENT_COUNTER,DECREMENT_COUNTER} from '../actions'; export default function counter(state = 0,action) { switch (action.type){ case INCREMENT_COUNTER: return state+1; case DECREMENT_COUNTER: return state-1; default: return state; } } 这里我们就是对增和减两个之前在action定义好的常量做了处理。 const rootReducer = combineReducers({ counter }); export default rootReducer; 每个 storestore是对之前说到一个联系和管理。具有如下职责
强调一下 Redux 应用只有一个单一的 结合react-redux的使用
如: export default class Counter extends Component{ render(){ const { counter,increment,decrement,incrementIfOdd,incrementAsync } = this.props; return( <p> Clicked:{counter} times <button onClick={increment}>+</button> <button onClick={decrement}>-</button> <button onClick={incrementIfOdd}>increment if Odd</button> <button onClick={incrementAsync}>increment async</button> </p> ) } } 容器组件特性则恰恰相反:
class App extends Component{ render(){ const { counter,incrementAsync } = this.props; return( <Counter counter={counter} increment={increment} decrement={decrement} incrementIfOdd={incrementIfOdd} incrementAsync={incrementAsync}/> ) } } export default connect( state=>({ counter: state.counter }),ActionCreators )(App);
redux-thunk一个比较流行的redux的action中间件,它可以让 const fetchDataAction = (querys) => (dispatch,getState) => { const setLoading = createAction('SET_LOADING'); dispatch(setLoading(true)); // 设置加载中。。。 return fetch(`${url}?${querys}`).then(r => r.json()).then(res => { dispatch(setLoading(false)); // 设置取消加载中。。。 dispatch(createAction('DATA_DO_SOMETHIN')(res)) }) } 这里我们的 dispatch(fetchDataAction(querys)) 在请求数据之前,通过 redux-promise既然说到了异步 import { createAction } from 'redux-actions'; class AsyncApp extends Component { componentDidMount() { const { dispatch,selectedPost } = this.props // 发出异步 Action dispatch(createAction( 'FETCH_DATA',fetch(`url`).then(res => res.json()) )); } 其实 redux-actions当我们的在开发大型应用的时候,对于大量的 createAction创建 import { createAction } from 'redux-actions'; createAction( type,// action类型 payloadCreator = Identity,// payload数据 具体参考Flux教程 ?metaCreator // 具体我也没深究是啥 ) 例子如下: export const increment = createAction('INCREMENT') export const decrement = createAction('DECREMENT') increment() // { type: 'INCREMENT' } decrement() // { type: 'DECREMENT' } increment(10) // { type: 'INCREMENT',payload: 10 } decrement([1,42]) // { type: 'DECREMENT',payload: [1,42] } createActions创建多个 import { createActions } from 'redux-actions'; createActions( actionMap,?...identityActions,) 第一个参数
例子如下 createActions({ ADD_TODO: todo => ({ todo }) REMOVE_TODO: [ todo => ({ todo }),// payloa (todo,warn) => ({ todo,warn }) // meta ] }); const actionCreators = createActions({ APP: { COUNTER: { INCREMENT: [ amount => ({ amount }),amount => ({ key: 'value',amount }) ],DECREMENT: amount => ({ amount: -amount }),SET: undefined // given undefined,the identity function will be used },NOTIFY: [ (username,message) => ({ message: `${username}: ${message}` }),(username,message) => ({ username,message }) ] } }); expect(actionCreators.app.counter.increment(1)).to.deep.equal({ type: 'APP/COUNTER/INCREMENT',payload: { amount: 1 },meta: { key: 'value',amount: 1 } }); expect(actionCreators.app.counter.decrement(1)).to.deep.equal({ type: 'APP/COUNTER/DECREMENT',payload: { amount: -1 } }); expect(actionCreators.app.counter.set(100)).to.deep.equal({ type: 'APP/COUNTER/SET',payload: 100 }); expect(actionCreators.app.notify('yangmillstheory','Hello World')).to.deep.equal({ type: 'APP/NOTIFY',payload: { message: 'yangmillstheory: Hello World' },meta: { username: 'yangmillstheory',message: 'Hello World' } }); 第二个参数 const { actionOne,actionTwo,actionThree } = createActions({ // function form; payload creator defined inline ACTION_ONE: (key,value) => ({ [key]: value }),// array form ACTION_TWO: [ (first) => [first],// payload (first,second) => ({ second }) // meta ],// trailing action type string form; payload creator is the identity },'ACTION_THREE'); expect(actionOne('key',1)).to.deep.equal({ type: 'ACTION_ONE',payload: { key: 1 } }); expect(actionTwo('first','second')).to.deep.equal({ type: 'ACTION_TWO',payload: ['first'],meta: { second: 'second' } }); expect(actionThree(3)).to.deep.equal({ type: 'ACTION_THREE',payload: 3,}); handleAction字面意思理解,处理 import { handleAction } from 'redux-actions'; handleAction( type,// action类型 reducer | reducerMap = Identity defaultState // 默认state ) 当第二个参数为一个reducer处理函数时,形式如下,处理传入的 handleAction('APP/COUNTER/INCREMENT',(state,action) => ({ counter: state.counter + action.payload.amount,}),defaultState); 当第二个参数为reducerMap时,也为处理 handleAction('FETCH_DATA',{ next(state,action) {...},throw(state,},defaultState); 官方推荐使用 handleActions与 import { handleActions } from 'redux-actions'; handleActions( reducerMap,defaultState )
import { createActions,handleActions } from 'redux-actions'; const { increment,decrement } = createActions({ 'INCREMENT': amount => ({ amount: 1 }),'DECREMENT': amount => ({ amount: -1 }) }); const reducer = handleActions({ [increment](state,{ payload: { amount } }) { return { counter: state.counter + amount } },[decrement](state,{ payload: { amount } }) { return { counter: state.counter + amount } } },defaultState); combineActions将多个 const { increment,decrement } = createActions({ INCREMENT: amount => ({ amount }),DECREMENT: amount => ({ amount: -amount }) }); const reducer = handleActions({ [combineActions(increment,decrement)](state,{ payload: { amount } }) { return { ...state,counter: state.counter + amount }; } },{ counter: 10 }); expect(reducer({ counter: 5 },increment(5))).to.deep.equal({ counter: 10 }); expect(reducer({ counter: 5 },decrement(5))).to.deep.equal({ counter: 0 }); expect(reducer({ counter: 5 },{ type: 'NOT_TYPE',payload: 1000 })).to.equal({ counter: 5 }); expect(reducer(undefined,increment(5))).to.deep.equal({ counter: 15 });
reselect
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,props) => { return { todolist: getVisibleTodos(state,props) } } 这个代码有一个潜在的问题。每当 const getVisibilityFilter = state => state.todo.showStatus const getTodos = state => state.todo.todolist const getVisibleTodos = createSelector([getVisibilityFilter,getTodos],(visibilityFilter,todos) => { switch (visibilityFilter) { case 'SHOW_COMPLETED': return todos.filter(todo => todo.completed) case 'SHOW_ACTIVE': return todos.filter(todo => !todo.completed) default: return todos } }) const mapStateToProps = (state,props) => { const todolist = getVisibleTodos(state,props); return { todolist } } 我们使用 最后总结了那么多的用法,其实也是 (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |