在ReactNative中使用ReduxjsToolkit

ReactNative中集成Redux Toolkit

在下边的案例中实现一个页面

在页面中有一个按钮

点击按钮实现redux中的数据更新

并显示到页面上

在这里插入图片描述

1 安装相关依赖

npm install @reduxjs/toolkit
npm install react-redux

package.json

"dependencies": {
      ...
    "@reduxjs/toolkit": "^2.0.1",
    "react-redux": "^7.2.5",
    "redux": "^4.1.1",
    "redux-thunk": "^2.3.0"
  },

2 创建configureStore

基本概念

configureStore

创建Redux存储的标准方法。它在内部使用低级Redux核心createStore方法,但对其进行封装,为存储设置提供良好的默认值,以获得更好的开发体验

import { configureStore } from '@reduxjs/toolkit'
// ...
const store = configureStore({
	// 在此处添加多个createSlice
  reducer: {
    one: oneSlice.reducer,
    two: twoSlice.reducer,
  }
})
export type RootState = ReturnType<typeof store.getState>

export default store

示例

创建redux/index.ts 文件

这个ts文件主要定义了一个configureStore对象,并向外暴露

configureStore 对象中有一个reducer,reducer用来定义多个createSlice对象

同时也选择性的暴露了一个RootState类型,供组件使用

// 导入configureStore
import {configureStore} from '@reduxjs/toolkit';

import testReducer from './modules/test';

// 创建一个store对象
const store = configureStore({
  reducer: {
    test: testReducer,
  },
});

export default store;
export type RootState = ReturnType<typeof store.getState>

3 创建createSlice

基本概念

createSlice

一个接受初始状态、reducer函数对象和“切片名称”的函数,并自动生成与reducer和状态对应的action和action types

function createSlice({
    // 一个名称, 将用于action types
    name: string,
    // 初始状态数据
    initialState: State,
    // 一个包含多个reducers. Key 的名称将被用于生成actions
    reducers: Record<string, ReducerFunction | ReducerAndPrepareObject>,
    // 用于添加更多reducers的“builder callback”函数
    extraReducers?: (builder: ActionReducerMapBuilder<State>) => void,
    // slice reducer的位置偏好,由`combineSlice`和`slice.selectors`使用。默认为“name”`
    reducerPath?: string,
    // 选择器对象,接收切片的状态作为其第一个参数.
    selectors?: Record<string, (sliceState: State, ...args: any[]) => any>,
})

示例

创建redux/modules/test.ts 文件

这个ts文件主要定义了一个createSlice对象,并向外暴露addInitialData这个action 以供组件调用

createSlice对象包含一下key

  • name - 一个命名空间,将被用于 action types
  • initialState - reducer的初始状态
  • reducers -包含多个 “reducers”的对象。Key 名称将用于生成actions的操作
import {createSlice} from '@reduxjs/toolkit';
const channelStore = createSlice({
  // 模块名
  name: 'test',

  // 初始化state数据
  initialState: {

    initialData: 0, // 初始化一个数据

  },
  // 编写修改数据的方法 同步方法 直接修改
  reducers: {
    /**
     * @param {*} state 是数据仓库
     * @param {*} action 是个对象 payload是真实数据
     */
    addInitialData(state, action) {
      console.log("==");
      
      state.initialData = action.payload + state.initialData;
    },
  },
});


// 向外暴露reducers 供组件修改initialState中的数据时使用
const {addInitialData} = channelStore.actions;
export {addInitialData};

// 默认导出reducer
export default channelStore.reducer;

4 在项目根组件导入configureStore

要在rn页面渲染redux中的数据

需要用 Provider 包裹项目根组件

将暴露的configureStore 传入 store属性中

import Navigator from './js/nav/index'; // 导航入口
import { Provider } from 'react-redux'; // 导入Provider
import store from './js/redux/index'; // 导入configureStore
import 'react-native-gesture-handler';

const Root = () => {
  return (
      <Provider store={store}>
          <Navigator />
      </Provider>
  );
}
export default Root;

5 在组件中使用

// 组件通信
import { Text, Button, StyleSheet, View } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import { RootState } from '../../redux/index'
import { addInitialData } from '../../redux/modules/test';

const styles = StyleSheet.create({
  container: {
    padding: 20,
  },
  title: {
    color: 'ba',
    fontWeight: 'bold',
    fontSize: 30,
  },
  reduxData: {
    marginBottom: 10,
    padding: 10,
    borderRadius: 2,
    backgroundColor: '#FFFAF0'
  }
});


export default function ReduxBase() {

  // 从store中取出test数据
  const test = useSelector((state: RootState) => state.test.initialData)

  // 导入dispatch函数
  const dispatch = useDispatch();

  // 改变redux中的数据
  function changeStoreData() {
    dispatch(addInitialData(1))
  }
  return (
    <>
      <View style={styles.container}>
        <Text style={styles.title}>修改redux中的数据</Text>
        <View style={styles.reduxData}>
          <Text>redux中的数据</Text>
          <Text>{test}</Text>
        </View>
        <Button
          onPress={changeStoreData}
          title="点我修改redux数据"
          color="#841584"
          accessibilityLabel="Learn more about this purple button"
        />
      </View>
    </>
  );
}

异步方法

在下边的案例中

演示如何通过Redux Toolkit实现异步调用接口请求数据

并将数据最终渲染到页面上

在这里插入图片描述

1创建新的reducers

基本概念

createAsyncThunk

一个接受Redux操作类型字符串和应返回promise的回调函数的函数。它根据您传入的操作类型前缀生成promise生命周期操作类型,并返回一个thunk操作创建者,该创建者将运行promise回调并根据返回的promise分派生命周期操作

这个函数接受两个参数 typepayloadCreator

const thunk = createAsyncThunk(type,payloadCreator )
type

一个字符串,用于生成额外的Redux操作类型常量,表示异步请求的生命周期

例如,“users/requestStatus”的类型参数将生成这些操作类型

  • pending: 'users/requestStatus/pending'
  • fulfilled: 'users/requestStatus/fulfilled'
  • rejected: 'users/requestStatus/rejected'
payloadCreator

一个回调函数,应该返回一个包含某些异步逻辑结果的promise。它也可能同步返回一个值。如果有错误,它应该返回一个包含error实例的被拒绝的promise或一个简单的值,如描述性错误消息,或者返回一个由thunkAPI.RejectWithValue函数返回的带有RejectWithValue参数的已解析promise

payloadCreator函数可以包含计算适当结果所需的任何逻辑。这可能包括一个标准的AJAX数据获取请求、将结果组合成最终值的多个AJAX调用、与React Native AsyncStorage的交互等等

payloadCreator函数将通过两个参数调用

  • arg: 一个单独的值,包含在分派thunk操作创建者时传递给它的第一个参数。这对于传入请求中可能需要的项目ID等值非常有用。如果需要传入多个值,请在分派thunk时将它们一起传递到一个对象中,如dispatch(fetchUsers({status:‘active’,sortBy:‘name’}))
  • thunkAPI: 一个对象,包含通常传递给Redux thunk函数的所有参数以及其他选项
extraReducers

extraReducers允许createSlice响应并更新自己的状态,以响应除其生成的类型之外的其他操作类型

其中extraReducers接受一个回调函数 参数为 builder

createSlice({
  name: 'counter',
  initialState: 0,
  reducers: {},
  extraReducers: (builder) => {
    builder
      .addCase(incrementBy, (state, action) => {
        // action is inferred correctly here if using TS
      })
  }
})

Builder 方法


builder.addCase

添加一个Reducer来处理单一的精确动作类型

所有对builder.addCase的调用都必须在对builder.addMatcher或builder.addDefaultCase的任何调用之前进行

参数

actionCreator 一个普通的动作类型字符串,或者由createAction生成的动作创建者,可用于确定动作类型

reducer 实际Reducer功能

builder.addMatcher

允许您将传入的操作与自己的筛选函数相匹配,而不仅仅是action.type属性

如果多个匹配器reducer匹配,则所有匹配器都将按照定义的顺序执行,即使一个case reducer已经匹配。所有对builder.addMatcher的调用都必须在对builder.addCase的任何调用之后,在对buildr.addDefaultCase的任何调用之前

参数

**matcher **匹配函数。在TypeScript中,这应该是一个类型谓词函数

reducer 实际Reducer功能

示例

创建redux/modules/testasyn.ts 在这个reducers里实现异步请求数据的功能

在这个案例中

主要用到了 createAsyncThunk 和 extraReducers 处理异步请求

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

// 导入一个异步请求数据的方法
import { getData } from '../../api/index'

// 声明异步Thunk
const infoQuery = createAsyncThunk(
  "testasyn/infoQuery",
  async () => {
  // 异步调用网络接口请求数据
    const data = await getData()
    return data
  }
)

const channelStore = createSlice({
  // 模块名
  name: 'testasyn',

  // 初始化state数据
  initialState: {
    info: {
      id: '',
      tag: '',
      name: '',
      origin: '',
      content: '',
      created_at: '',
      updated_at: ''
    }
  },
  reducers: {
  },
  // 额外的Reducers处理
  extraReducers: (builder) => {
    // 当异步action处理完调用
    builder.addCase(infoQuery.fulfilled, (state, action) => {
      state.info = action.payload;
    })

    // 当异步action处理中调用
    builder.addCase(infoQuery.pending, (state) => {
      console.log("加载中");
    })
    // 当异步action出错调用
    builder.addCase(infoQuery.rejected, (state, action) => {
      console.log("出错了");
    });
  }
});

// 导出actionCreater
export { infoQuery };

// 默认导出reducer
export default channelStore.reducer;

2.在configureStore中导入创建的reducers

在redux/index.ts 文件中

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

import testReducer from './modules/test';
import testAsynReducer from './modules/testasyn';

const store = configureStore({
  reducer: {
    test: testReducer,
    testAsyn: testAsynReducer,
  },
});

export default store;

export type RootState = ReturnType<typeof store.getState>

3在组件中使用

// 异步组件通信
import { Text, Pressable } from 'react-native';
import { useDispatch, useSelector } from 'react-redux';
import { RootState } from '../../redux';
import { infoQuery } from '../../redux/modules/testasyn';

export default function ReduxBase() {
  const dispatch = useDispatch();

  // 从store中取出异步的数据
  const info = useSelector((state: RootState) => state.testAsyn.info)

  // 触发异步操作
  function getDataAsyn() {
    dispatch(infoQuery())

  }
  return (
    <>
      <Pressable onPress={getDataAsyn}>
        <Text>点我异步请求数据</Text>
      </Pressable>
      <Text>{info.id}</Text>
      <Text>{info.tag}</Text>
      <Text>{info.name}</Text>
      <Text>{info.origin}</Text>
      <Text>{info.content}</Text>
      <Text>{info.created_at}</Text>
      <Text>{info.updated_at}</Text>
    </>
  );
}




评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值