Taro中学习使用react-redux+Toolkit+TypeScript构建小程序自定义tabbar

2,665 阅读3分钟

背景

学习taro从0开发一款会员系统帮助家里摆脱手账本第二天,完成项目顺便学习相关技术栈技术。

初步框架选择,前端:taro+react+ts相关技术栈,后端:egg+mysql相关技术栈

进度:已经绘制好基础功能原型图,使用taro完成首页页面开发,完成自定义tabbar。

接下来修改首页样式,完成我的页面,会员注册页面,特权卡相关页面的基础前后端功能。

QQ20220126-030149@2x.png 微信自带的tabbar样式不太喜欢,打算自定义tabbar,初次接触react-redux配合ts踩了一些坑,记录一下最后的结果。

新建自定义tabbar文件

参考微信小程序文档:developers.weixin.qq.com/miniprogram…

根目录新建文件"/custom-tab-bar/index.tsx"

import { View } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { useState, useEffect } from 'react';
// 使用的taro-ui组件库里的tabbar
import { AtTabBar } from 'taro-ui'
// tabbar的配置json
import tabbarConfig from '../config/tabbar'
// index.scss里面是引入taro-ui tabbar样式
import './index.scss'const CustomTabBar = () => {
  // 定义显示的current
  const [current, setCurrent] = useState(0);
  
  // 触发tabbar点击事件,修改tabbar的current
  const handleClick = (value) => {
    setCurrent(value);
    const url = '/' + tabbarConfig[value].pagePath;
    Taro.switchTab({ url })
  }
  return (
    <View>
      <AtTabBar
        tabList={[
          { title: '首页', iconType: 'bullet-list', text: 'new' },
          { title: '会员', iconType: 'camera' },
        ]}
        onClick={handleClick.bind(this)}
        current={current}
      />
    </View>
  );
}
​
export default CustomTabBar;

出现了tabbar切换时选择状态也跟着刷新,没有记录状态。

使用react-redux

参考案例:codesandbox.io/s/github/re…

参考文档:

Redux Toolkit Quick Start

React Redux+TS

React Redux+hooks

taro官方redux使用方法

  1. 新建"/reducers/tabbarSlice.ts",里面是tabbar的数据和设置方法。
import { createSlice, PayloadAction } from "@reduxjs/toolkit";
​
// Define a type for the slice state
interface TabbarState {
  current: number;
}
​
// Define the initial state using that type
const initialState: TabbarState = {
  current: 0
};
​
export const tabbarSlice = createSlice({
  name: "tabbar",
  initialState,
  reducers: {
    setTabbar: (state, action: PayloadAction<number>) => {
      state.current = action.payload;
    }
  }
});
​
// 导出方法
export const { setTabbar } = tabbarSlice.actions;
export default tabbarSlice.reducer;
  1. 新建"/reducers/index.ts",集体引入所有的slice文件,目前就一个tabbarSlice.ts
import { combineReducers } from "redux";
import tabbar from "./tabbarSlice";
​
export default combineReducers({ tabbar });
​
  1. 新建"/store/index.ts",创建store
import { configureStore } from "@reduxjs/toolkit";
import reducer from "../reducers";
export const store = configureStore({
  reducer
});
​
// 导出state的样式
export type RootState = ReturnType<typeof store.getState>;
export type AppDispatch = typeof store.dispatch;
  1. 修改入口文件"/app.tsx",使用Provider包裹传递store
import { FC } from "react";
import { Provider } from "react-redux";
import { store } from "./store";
​
import "./app.scss";
​
const App: FC = (props) => {
  return (
    <Provider store={store}>
      {props.children}
    </Provider>
  );
}
​
export default App
  1. 新增Hook文件"/hooks/store.ts",主要为了省略代码,封装一层能够自动设置样式类型的hook。
import { TypedUseSelectorHook, useDispatch, useSelector } from 'react-redux';
import type { RootState, AppDispatch } from '../store';
​
export const useAppDispatch = () => useDispatch<AppDispatch>();
export const useAppSelector: TypedUseSelectorHook<RootState> = useSelector;
  1. 修改自定义tabbar文件,新增了react-redux使用
import { View } from '@tarojs/components';
import Taro from '@tarojs/taro';
import { useState, useEffect } from 'react';
import { AtTabBar } from 'taro-ui'
import tabbarConfig from '../config/tabbar'// 新增react-redux相关 使用封装好的hooks
import { useAppSelector, useAppDispatch } from '../hooks/store'
import { setTabbar } from '../reducers/tabbarSlice'import './index.scss'const CustomTabBar = () => {
  // 获取当前tabbar的current
  const tabCurrent = useAppSelector((state) => state.tabbar.current);
  const dispatch = useAppDispatch()
​
  // 定义显示的current
  const [current, setCurrent] = useState(0);
​
  // 监听修改了tabbar就触发当前修改
  useEffect(() => {
    setCurrent(tabCurrent)
  }, [tabCurrent])
​
  // 触发tabbar点击事件,修改tabbar的current
  const handleClick = (value) => {
    dispatch(setTabbar(value));
    setCurrent(value);
    const url = '/' + tabbarConfig[value].pagePath;
    Taro.switchTab({ url })
  }
  return (
    <View>
      <AtTabBar
        tabList={[
          { title: '首页', iconType: 'bullet-list', text: 'new' },
          { title: '会员', iconType: 'camera' },
        ]}
        onClick={handleClick.bind(this)}
        current={current}
      />
    </View>
  );
}
​
export default CustomTabBar;

这里已经实现了点击tabbar的状态保存了,但是还存在首次进入任何页面都是默认首页的tabbar状态,因为设置current默认值为0,所以需要修改一下每个tabbar页面。

修改tabbar中的所有页面,以"/pages/my/my.tsx"为例

import { View } from '@tarojs/components'
import './my.scss'import { useAppDispatch } from '../../hooks/store'
import { setTabbar } from '../../reducers/tabbarSlice'const My = () => {
  const dispatch = useAppDispatch();
  // 修改current为对应tabbar值,my页面索引为1
  dispatch(setTabbar(1));
  return (
    <View className='my'>
      <View className="at-row">
        <View className="at-col-6">
          头像
        </View>
        <View className="at-col-6">
          二维码
        </View>
​
      </View>
    </View>
  )
}
export default My;

总结

学习react-redux中绕了很多坑,从redux看起,似懂非懂的感觉,使用起来又千奇百怪,各种用法,使用react-redux有提供Toolkit工具可以更加简单的使用,本来用@connect方式实现了一次,但是看到官网文档上推荐使用hook的方式,又修改了一下。