美文网首页
【React Native教程】Redux入门教程

【React Native教程】Redux入门教程

作者: ZephyrCo | 来源:发表于2020-08-06 11:01 被阅读0次

Redux定义

Redux官网上是这么定义的:A Predictable State Container for JS Apps,直译过来就是一个使用在JS应用上的可预测的状态容器。

Redux解决的问题

React Native本身是基于前端的React框架,它是通过State来管理页面显示和参数更新。如果在交互比较复杂的页面、需要多页面状态传递或者同步更新的情况,状态管理就会比较麻烦。使用Redux就可以解决这些问题。

Redux的核心逻辑

Redux的核心逻辑是集中定义和管理状态和动作执行,各个页面使用connect方法绑定相应的方法和状态,并通过发送动作指令更新页面显示。达到状态和操作与页面隔离的效果。

State

State即状态,是React框架最基础的概念之一,通过更改状态实时更新页面显示。

{
    prop1: value1,
    prop2: value2,
}

Action

Action是指指令或者动作。在Redux中,页面不直接管理状态,每个页面都是通过发送Action间接地更新状态。Action中有两个参数,一个是Type,字符串类型,代表Action的类型和唯一标识,一个是payload,代表传递的参数,可以是任意类型。

{
    type: 'EXAMPLE_ACTION',
    payload: 'args'
}

Reducer

Redux中状态和动作都是集中管理,管理者被称为ReducerReducer接收StateAction参数,根据传过来的Action类型和参数进行处理并更新State

function rootReducer(state = initialState, action) {
  if (action.type === 'FIRST_ACTION') {
    return Object.assign({}, state, {
      props: newValue
    });
  }
  return state;
}

Slice

在以往的Redux使用中,我们需要自己创建ActionReducer,并用Switch或者if else语句区分不同的Action,步骤非常繁琐。现在Redux官方推荐使用更方便更现代化的工具@reduxjs/toolkit,这个工具集成了createActioncreateReducer等方法,非常方便。不过这两个方法一般也不用,在tookit提供了一个新的类Slice,创建**Slice时也会同时创建StateReducerAction

const mySlice = createSlice({
    name: "sliceName",
    initialState: {
        prop1: "",
        prop2: false,
    },
    reducers: {
        action1: (state, action) => {
            console.debug('action1 done'+action.type);
        },
        action2: (state) => {
            state.prop1 = "123";
            state.prop2 = true;
        },
    },
});

在需要使用ReducerAction时,直接抽取即可

const { action1, action2 } = authSlice.actions;
const myReducer = mySlice.reducer;

Thunk

上面介绍的是普通Action,但如果是执行的动作需要异步执行后更新状态的就不适用了,因此Redux引入了中间件Thunk,在引入@reduxjs/toolkit后创建异步Action方法如下:

export const doLogin = createAsyncThunk(
    'user/login',
    async ({username, password, code}) => {
        return await API.fetchData({
            path: 'doLogin',
            params: {
                code: code,
                password: AESTool.encrypt(password),
                userName: username,
            }
        });
    },
    {
        condition: ({username, password, code}) => {
            if (checkStringEmpty(username)) {
                HUD.show("请输入用户名!");
                return false;
            } else if (checkStringEmpty(password)) {
                HUD.show("请输入密码!");
                return false;
            } else if (checkStringEmpty(code)) {
                HUD.show("请输入验证码!");
                return false;
            }
            return true;
        },
        dispatchConditionRejection: true
    }
)

在上面的代码中,在condition可以控制这个异步Action是否可以继续执行,如果返回falseAction会终止执行而且没有回调。如果希望返回false后有rejected回调,可以设置dispatchConditionRejectiontrue

异步Action执行完成后,回调是在SliceextraReducers中,异步Action有三个状态:pendingfulfilledrejected,分别代表正在执行、成功执行和执行失败

extraReducers: {
    [ doLogin.pending ]: () => {
        Loading.show();
    },
    [ doLogin.fulfilled ]: (state, action) => {
        Loading.hidden();
        console.debug(action.payload)
    },
    [ doLogin.rejected ]: (state, action) => {
        Loading.hidden();
        console.warn(action.error);
    },
}

Store

StoreRedux的核心类,它的作用是管理所有的Reducer和中间件,并作为参数传递到项目的根视图组件中。

const middleware = [
    ...getDefaultMiddleware(),
    CustomMiddleWare,
];

export const store = configureStore({
    reducer: {
        auth: authReducer,
        common: commonReducer
    },
    middleware,
});

<Provider store={store}>
    <StatusBar barStyle={'light-content'}/>
    <App/>
</Provider>

Redux在React Native中的使用

下面以一个简单的计数器为例讲解一下如果在React Native中使用Redux

安装依赖

首先需要安装@reduxjs/toolkit,可以使用NPM或者Yarn

# NPM
npm install @reduxjs/toolkit

# Yarn
yarn add @reduxjs/toolkit

然后安装Redux核心库

# NPM
npm install redux

# Yarn
yarn add redux

创建Slice

创建Slice时会同步创建StateReducer

import {createSlice} from '@reduxjs/toolkit';

const countSlice = createSlice({
    name: "count",
    initialState: {
        value: 0
    },
    reducers: {
        incrementAction: (state, action) => {
            state.value += action.payload;
        },
        decrementAction: (state, action) => {
            state.value -= action.payload;
        },
    },
});

export const {incrementAction, decrementAction } = countSlice.actions;

export const countReducer = countSlice.reducer;

在这里创建了名为countSlice,计算器初始值为0,并在Reducer中定义了两个ActionincrementActiondecrementAction,根据传过来的参数确定每次加减的数值。后面两行export代码确保外部能够访问这里创建的Actionreducer

创建Store

接下来就是创建Store,创建时会传入刚刚创建的reducer

注意:在页面获取状态值的时候中间一定要先获取reducer,然后再获取reducer里的状态值,例如获取countReducer里的valuestate.count.value

import {configureStore, createSlice, getDefaultMiddleware} from "@reduxjs/toolkit";
import {countReducer} from './slices/CountSlice'

const middleware = [
    ...getDefaultMiddleware(),
];

export const store = configureStore({
    reducer: {
        count: countReducer, 
    },
    middleware,
});

至此,Redux部分就准备好了,接下来就是页面的交互部分了。

页面嵌入Redux

index.js文件中将Provider更改为App的根控件,并传入store作为参数:

AppRegistry.registerComponent(appName, () => ProviderContainer);

const ProviderContainer = () => {
    return (
        <Provider store={store}>
            <App/>
        </Provider>
    );
}

下面是App.js的主要代码


class App extends Component {

  constructor(props) {
    super(props);
    this.state = {
      num: 1
    }
  }

  render() {
    return (
        <>
          <StatusBar barStyle="dark-content" />
          <SafeAreaView>
            <View style={styles.container}>
              <TextInput style={styles.textInput} onChangeText={(text)=>{
                this.setState({
                  num: parseInt(text)
                })
              }}>{isNaN(this.state.num) ? 1 : this.state.num}</TextInput>
              <View style={styles.buttonContainer}>
                <TouchableOpacity style={styles.button} activeOpacity = {.9} onPress={() => {
                  this.props.decrement(this.state.num)
                }}>
                  <Text style={styles.buttonText}>-</Text>
                </TouchableOpacity>
                <Text style={styles.text}>{this.props.value}</Text>
                <TouchableOpacity style={styles.button} activeOpacity = {.9} onPress={() => {
                  this.props.increment(this.state.num)
                }}>
                  <Text style={styles.buttonText}>+</Text>
                </TouchableOpacity>
              </View>
            </View>
          </SafeAreaView>
        </>
    );
  }

}

const mapStateToProps = (state) => {
  return {
    value: state.count.value,
  }
}

function mapDispatchToProps(dispatch) {
  return {
    increment: (num) => dispatch(incrementAction(num)),
    decrement: (num) => dispatch(decrementAction(num)),
  };
}

export default connect(mapStateToProps, mapDispatchToProps)(App);

App.js

上面的TextInput用于输入每次增加或者减小的数值,下面有一个加号按钮和一个减号按钮,中间是显示当前数值的文本。

mapStateToPropsmapDispatchToProps,的作用是映射Slice中定义的StateAction到当前页面,在使用时直接this.props.value调用即可。最后通过Reduxconnect方法将这些映射和当前页的组件连接起来。

以上就是Redux的入门教程,想深入了解Redux的使用可以参考官方文档,本文的Demo可以在这里查看。

相关文章

网友评论

      本文标题:【React Native教程】Redux入门教程

      本文链接:https://www.haomeiwen.com/subject/nbovrktx.html