React Native 開發豆瓣評分(三)集成 Redux

什麼是 redux

redux 是一個用於管理 js 應用狀態(state)的容器。好比組件 A 發生了變化,組件 B 要同時作出響應。常見的應用場景就是用戶的登陸退出操做:未登陸狀態,我的中心顯示登陸按鈕,在登陸頁面進行了登陸後,須要在我的中心頁面作出相應,顯示我的信息。相似的產品有: vuex、flux、dva、mobx。vue

redux 常見爲三個部分:react

  • Action:存放改變 Store 內容的方法,想要改變 Store 裏面的數據,只能觸發 Action 裏面的相關方法;
  • Reducer:根據 Action 操做作出不一樣的響應,返回一個新的 Store;
  • Store:儲存數據。

在本應用裏使用 redux 主要用於保存用戶狀態、保存首頁數據。git

在 React Native 裏面使用 redux

安裝相關依賴

yarn add redux redux-persist react-redux
  • redux 、react-redux:用於存儲應用狀態;
  • redux-persist:用於離線存儲狀態,退出應用後再次進入應用,狀態任然存在。

編輯 Action

在 src 目錄下建立 action 目錄,目錄中建立 index.js。github

這裏建立 2 個應用中要用到的方法,login(登陸)、logout(退出);2 個測試 redux 是否生效的方法,add(加大數字)、cut(減小數字)。vuex

export function add(num) { // 每一個函數的返回值裏面必須得有一個type值,Reducer就是根據type值改變作出相應
    return {
        type: 'add',
        value: ++num
    }
}

export function cut(num) {
    return {
        type: 'cut',
        value: --num
    }
}

export function login(data) {
    return {
        type: 'login',
        data
    }
}

export function logout(data) {
    return {
        type: 'logout',
        data
    }
}

編輯 Reducer

在 src 目錄下建立 reducer 目錄,目錄中建立 index.js/num.js/user.js。redux

index.jsreact-native

import { combineReducers } from 'redux';
import num from './num';
import user from './user';

//這裏返回的combineReducers()就是 Store 的內容,後面想要得到的話,就是使用 store.user、store.num來得到對應store的數據
export default combineReducers({
    num: num,
    user: user
})

num.jsapp

const initState = {//初始化state內容
    value: 0
}

const setNumState = (state = initState, action) => {
    switch (action.type) {//根據type的不一樣作出不一樣的響應
        case 'add':
            return {
                ...state,
                value: action.value,
                status: 'add'
            }
        case 'cut':
            return {
                ...state,
                value: action.value,
                status: 'cut'
            }
        default://必須得有default,用於返回非指望的狀態
            return state;
    }
}

export default setNumState;

user.jside

const initState = {
    isLogin: false,
    userData: {}
}

const setUserState = (state = initState, action) => {
    switch (action.type) {
        case 'login':
            return {
                ...state,
                isLogin: true,
                userData: action.data
            }
        case 'logout':
            return initState;
        default:
            return state;
    }
}

export default setUserState;

編輯 Store

在 src 目錄下建立 store 目錄,目錄中建立 index.js。函數

import { AsyncStorage } from 'react-native';
import { createStore } from 'redux';
import { persistStore, persistReducer } from 'redux-persist';
import hardSet from 'redux-persist/lib/stateReconciler/hardSet';
import reducer from '../reducer';

//配置redux-persist,但下次進入應用,就會從root裏面得到數據
let persistConfig = {
    key: 'root',
    storage: AsyncStorage,
    stateReconciler: hardSet
}
const persistedReducer = persistReducer(persistConfig, reducer);
export default function configureStore() {
    const store = createStore(persistedReducer);
    let persistor = persistStore(store);
    return { store, persistor };
}

修改 App.js

import React, { Component } from 'react';
import { Provider } from 'react-redux';
import { PersistGate } from 'redux-persist/integration/react';
import configureStore from './store';
import Router from './router';

const store = configureStore();

export default class App extends Component {
  render() {
    return (
      <Provider store={store.store} style={{ flex: 1 }}>
        <PersistGate loading={null} persistor={store.persistor}>
          <Router />
        </PersistGate>
      </Provider>
    );
  }
};

修改 pages 裏面的 index.js detail.js 以測試 redux 是否生效

import React from "react";
import { View, Text } from "react-native";
import { connect } from 'react-redux';
import { add, cut } from '../action';


class Home extends React.Component {
  render() {
    const { dispatch, value, navigation } = this.props;
    return (
      <View style={{ flex: 1, alignItems: "center", justifyContent: "center" }}>
        <Text onPress={() => navigation.push('Detail')}>Home Click Me</Text>
        <View style={{ flexDirection: 'row', width: 300, justifyContent: 'space-around' }}>
          <Text onPress={() => dispatch(add(value))} style={{ backgroundColor: 'blue', color: '#fff', fontSize: 18 }}>減小數字</Text>
          <Text style={{ fontSize: 20 }}>{value}</Text>
          <Text onPress={() => dispatch(cut(value))} style={{ backgroundColor: 'blue', color: '#fff', fontSize: 18 }}>加大數字</Text>
        </View>
      </View>
    );
  }
}

const select = (store) => {
  return {
    value: store.num.value,
  }
}

export default connect(select)(Home);

效果圖:

這裏是一個集成了 router、redux、icons的基本工程,clone下來就能使用 https://github.com/hulinNeil/react-native-base;

相關文章
相關標籤/搜索