背景
学习taro从0开发一款会员系统帮助家里摆脱手账本第二天,完成项目顺便学习相关技术栈技术。
初步框架选择,前端:taro+react+ts相关技术栈,后端:egg+mysql相关技术栈
进度:已经绘制好基础功能原型图,使用taro完成首页页面开发,完成自定义tabbar。
接下来修改首页样式,完成我的页面,会员注册页面,特权卡相关页面的基础前后端功能。
微信自带的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…
参考文档:
- 新建"/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;
- 新建"/reducers/index.ts",集体引入所有的slice文件,目前就一个tabbarSlice.ts
import { combineReducers } from "redux";
import tabbar from "./tabbarSlice";
export default combineReducers({ tabbar });
- 新建"/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;
- 修改入口文件"/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
- 新增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;
- 修改自定义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的方式,又修改了一下。