Redux總結

weixin_34087301發表於2018-02-28

首先沒有使用Redux的時候,我們的程式是這樣寫的。 對於需要改變的資料,我們需要使用state,程式碼如下:

export default class App extends Component {
  //定義了state的物件格式 通過setState方法來渲染介面
  state = { input: "" }
  render() {
    return (
      <View style={styles.container}>
        <TextInput style={styles.text} value={this.state.input}
          placeholder='請輸入你的內容' onChangeText={(text) => this.setState({input:text})}/>
        <Text style={styles.text}> 輸入的內容:{this.state.input } </Text>
      </View>
    );
  }
}

那如果使用 redux要怎麼做呢?

Redux是什麼?傳送門

首先了解Redux是JS庫,增加了 storeactionreducer 的概念,規範了全域性一個 state,從而只需要根據這個 state 就能回朔出整個應用的狀態。元件通過 dispatch 將 action 傳到 store,reducer 根據原來的 state 以及 action,返回新的 state,元件根據新的 state 渲染介面。

原來的state是儲存在元件類內部,現在由Redux統一管理,存放在stone裡面,改變他的唯一方法就是傳送action。Redux接收到action後,會交給對應的reducer去處理。

action是JS物件,按照約定,action 內必須使用一個字串型別的 type 欄位來表示將要執行的動作。


1825062-52b1a82058215d70.png
action約定
{
  type: '新增action',
  error: ' ',
  payload:' '
}
//或者通過函式的方式返回一個action
export const reduceActionCreate = (text) => {
    return {
        type: '減少action',
        payload:{  
            text:'  '
        }
    }
}

Reducers 指定了應用狀態的變化如何響應 actions 併傳送到 store 的, actions 只是描述了事情來了,誰來處理事情呢?當然就是我們們的Reducers。
處理完事情難道就白乾了,肯定得有所返回?首先我們們得先設計State的格式。如上面程式碼
const defaultState = { input: "" , other:' 123 '}
reducer 不神祕,其實就是一個純函式,接收舊的 state 和 action,返回新的 state。
(previousState, action) => newState

  //開始的時候 previousState為undefined狀態,所有要加個初始值
  function handlerReducers(previousState = defaultState , action) => {
    switch (action.type) {
      case '新增action':
        //複寫上一狀態的input屬性
        return {...previousState,input:action.payload}
      case '減少action':
        return {...previousState,input:action.payload}
      default:
        return state
    }
  }

當然每個 reducer只能管理自己的資料處理,如果有多個場景需要多個reducer,那要這麼做呢?

import { combineReducers } from 'redux'
//aaaa,bbbb兩個reducer,通過combineReducers函式 建立多Reducer的物件
const todoApp = combineReducers({
   AA: aaaa,
   BB: bbbb
})

export default todoApp 

Store其實就是處理容器,Reducer要處理action必須在我這做,怎麼做呢?首先我們們得先建立store
let store = createStore( 我們們的Reducers )
然後傳送處理action
store.dispatch(要處理的action)

到這裡我們們基本瞭解了Redux的使用方法,但是如何在我們的react專案使用呢?

這裡需要再強調一下:Redux 和 React 之間沒有關係。Redux 支援 React、Angular、Ember、jQuery 甚至純 JavaScript

既然沒有關係,怎麼樣讓他建立關係呢?傳送門
下面我們們簡單敘述下如何在我們的專案中配置Redux~~~

  1. 安裝 redux react-redux(rn和redux之間互動的一個庫)
    npm install --save redux react-redux
  2. 在app.js的控制元件的根路徑上,Provider元件去包裹。需要設定store屬性,通過createStore函式來建立。
import { Provider} from "react-redux";
render() {
    return (
      <Provider store={createStore(reducers)}>
        <MainScreen/>
      </Provider>
    );
  }
//reducers的程式碼
import { combineReducers } from "redux";

const defaultStatus = { input: '' ,other:'123'}

export default combineReducers({
    nullReducer: inputProcess
})

function inputProcess(pStatus = defaultStatus,action) {
    switch (action.type) {
        case 'aaa':
            return {...pStatus,input:action.payload}
        default:
            return pStatus;
    }
}
  1. 然後我們們要把redux和react建立聯絡。我們們需要用到connect的函式
    import { connect } from "react-redux";
    connect函式需要兩個引數mapStateToProps(state),mapDispatchToProps(dispatch),從方法名可以看出通過對映的方式將redux和react建立聯絡。mapStateToProps是將 reducers裡面的state對映成控制元件裡面的prop呼叫,mapDispatchToProps是將原先需要dispatch(action)的函式對映成props裡的函式呼叫。如下:
//將state 對映為 this.props.inputProps
function mapStateToProps(state){
   return {
     inputProps: state.nullReducer
   }
}

//想在元件訪問state資料
this.props.inputProps.****

//將需要Dispatch(Action)對映到props 下面例子將changeText函式對映changeTextActions
function mapDispatchToProps(dispatch) {
  return {
    changeTextActions: bindActionCreators(changeText, dispatch),
  };
}

//下面在想呼叫changeText方法,就呼叫prop裡面changeTextActions函式
this.props.changeTextActions(text)

想了解bindActionCreators() 點選這裡

//connect(**,**)方法返回也是個函式wrapWithConnect(元件)
connect(mapStateToProps,mapDispatchToProps)(MainScreen); 

//當然也可以簡潔的寫法 
export default connect((state)=>{ return { inputProps:state.nullReducer } },{changeTextActions})(MainScreen);

到這裡就完成redux的配置和程式碼修改。效果和文章開頭的效果差不多,但是程式碼多了很多。