Notes on React + TypeScript + Taro Frontend Development
Preface The project has reached a stopping point, so I'll jot some notes down first. This article records, from a frontend beginner's perspective, my development experience with React, TypeScript, and Taro, as well as the problems I ran into and how I solved them. I had always said I wanted to learn React (this blog post: Code Gives Me a Headache: First Steps with React). This project needed an H5 frontend plus a mini program, so I finally got to use React~ I had heard of JD's Taro as a React development framework before, so I went with that and started coding right away. About React Pretty good. It feels much freer than Vue's template syntax
目录17 个章节
Preface
The project has reached a stopping point, so I'll jot some notes down first. This article records, from a frontend beginner's perspective, my development experience with React, TypeScript, and Taro, as well as the problems I ran into and how I solved them.
I had always said I wanted to learn React (this blog post: Code Gives Me a Headache: First Steps with React). This project needed an H5 frontend plus a mini program, so I finally got to use React~
I had heard of JD's Taro as a React development framework before, so I went with that and started coding right away.
About React
Pretty good. It feels much freer than Vue's template syntax. The examples in the Taro docs are all class components, but from the start my "frontend mentor" recommended function components. Now I use function components for everything—this is how React should be written. So good~
Because I had written Flutter for a while before, React felt familiar to me. At least I could pick up the declarative UI style seamlessly.
But I feel React's ecosystem is too large and updates too fast—it's a bit fragmented. A lot of third-party libraries' official docs can't keep up with the update pace (a little criticism for MobX here—it really led people astray)
Speaking of which, at first I read some Zhihu influencer's book on React and Redux. Probably because I'm too much of a noob, it didn't feel very easy to understand. I guess being a technically strong expert doesn't necessarily mean you're also good at teaching~
References
- Getting Started with React - Understanding React from a JS Perspective: https://github.com/coppyC/blog/issues/16
About TypeScript
First time using TypeScript, but as someone who writes backends in C# day to day, it felt familiar all over again~
Anyway, it's ten thousand times better than JS, that's for sure. Type hints are just amazing.
I haven't used it very deeply yet. If I run into more related stuff later, I'll write another blog post about it.
References
- Exploring TypeScript Type Annotations - Custom Types: https://github.com/WowBar/blog/issues/9
Impressions of the Taro Framework
The framework is a good framework, but the documentation doesn't feel very complete yet. Some parts aren't written very clearly. A lot of the docs feel like they were copied from the WeChat Mini Program docs, which isn't very friendly for people who haven't developed WeChat Mini Programs and haven't read the official WeChat docs. (You still need to read the official docs though—otherwise you won't be able to look up a lot of the problems you run into.)
Taro officially provides a UI library called TaroUI. It's usable, just that updates are too slow. Its GitHub project page shows the last update was still June of last year (2021)—it hasn't been touched in nearly a year. The latest stable version is still 2.x, while the Taro framework has already been updated to version 3.
Since I was using Taro 3.x, I had no choice but to grit my teeth and use the TaroUI 3 beta, which led to some weird issues. What a headache.
Besides the TaroUI UI library, Taro also officially provides another library called NutUI, but it's Vue-based, so I couldn't use it for this project. That library is updated quite diligently—the latest update on GitHub was still 6 hours ago, and it also has 4.2k stars, more than TaroUI's 3.9k. (Looks like React isn't favored at JD~).
I also saw a UI library called Taroify. It looks pretty good and is updated frequently too, but it only has a little over 300 GitHub stars, so I didn't dare use it~ I'll try it next time.
While using it I also referred to these projects/code/docs:
- https://github.com/NervJS/taro-v2ex/blob/react/src/pages/thread_detail/thread_detail.tsx
- https://github.com/wuba/Taro-Mortgage-Calculator
- https://github.com/NervJS/awesome-taro
Now on to the main topic. Overall I'll talk about some issues/pitfalls I ran into, and the solutions.
Page Routing Issues
Taro wraps routing-related methods. It wasn't until I finished the project and had time to flip through the WeChat Mini Program docs that I realized this thing is especially similar to mini program routing.
PS: I hate this kind of routing design. I don't know which genius came up with this for mini programs. When there are a lot of pages it's not easy to maintain~
Configure the routes in the app.config.ts file, something like this:
export default defineAppConfig({
pages: [
'pages/index/index',
'pages/info/place',
'pages/supply/index',
'pages/user/login',
],
window: {
backgroundTextStyle: 'light',
navigationBarBackgroundColor: '#fff',
navigationBarTitleText: 'WeChat',
navigationBarTextStyle: 'black'
},
})
Then wherever you need to navigate, just use Taro.navigateTo({url: 'pages/user/login'})
Here's a real pitfall! Taro's hot reload is incomplete. After adding a new page, hot reload doesn't take effect—you have to restart with yarn dev:h5 to see the result. I got burned by this at the start and was howling~
URL Parameter Issues
I mentioned this issue in a previous blog post: Implementing Enterprise WeChat Login in a Django + Taro Decoupled Frontend-Backend Project. Taro itself provides useRouter() for us to read parameters from the URL.
For example, if we add parameters at that navigation above: Taro.navigateTo({url: 'pages/user/login?title=hello'})
Then getting the parameters in the pages/user/login page would be like this
import {useEffect} from "react"
import {useRouter} from "@tarojs/taro"
export default function () {
const router = useRouter()
useEffect(() => {
console.log(router.params.title)
}, [])
}
But when reading the WeChat login server callback parameters, it doesn't work—you just can't get them. You have to take the full URL window.location.href and match it yourself. See this blog post of mine for details: Implementing Enterprise WeChat Login in a Django + Taro Decoupled Frontend-Backend Project
Taro.relaunch Doesn't Clear the URL
This doesn't look like a big issue, but it did cause a small bug: after using WeChat login, logging out doesn't clear the code in the URL. So if you don't close the page and use WeChat login again, that code is still the old one, and it just errors out~
TaroUI Form Bug
To be honest I don't know where this problem comes from
Only one page had this issue. Pressing Enter in the last input box looked like a form submit, but it didn't actually submit, and the page refreshed instead.
I just couldn't figure it out no matter how hard I thought
I had no choice but to add a hidden input at the very end
<AtInput
name='hide'
onChange={() => {
}}
disabled={true}
border={false}
style={{display: 'none'}}/>
Wrapping Network Requests
The Taro framework comes with Taro.request that can be used for requests, but when I used it I kept getting weird CORS errors. Because time was tight early on, I didn't dig into it and just switched to the axios wrapper I had from a previous Vue project. Sure enough, axios is still nicer to use~
(Though if we turn it into a mini program later, we'll probably still need to refactor. I hear mini programs don't support formdata)
Wrapping useState
Thanks to "frontend mentor coppy" for providing this code~
import {useState} from 'react'
export default function useYourState<T extends {}>(state: T): [T, (state: Partial<T>) => void] {
const [_state, _setState] = useState(state);
return [
_state,
(state: Partial<T>) => {
_setState((_state) => {
return {
..._state,
...state
};
});
}
];
}
This way you don't need to add ...state every time you setState.
Before:
import {useState} from 'react'
export const LoginPage = observer(() => {
const [state, setState] = useState({
username: '',
password: '',
})
setState({
...state,
username: '', password: ''
})
}
After:
import useYourState from "@/utils/coppy_state";
export const LoginPage = observer(() => {
const [state, setState] = useYourState({
username: '',
password: '',
})
setState({
username: '', password: ''
})
}
Productivity went up~
Global State Management
I didn't go with the famous Redux, and instead used the relatively simpler MobX.
But the example docs I found weren't great (for example, the official Chinese docs: https://cn.mobx.js.org/)
In the end I still sought help from my "frontend mentor" and got it working.
Pitfalls:
- Stores can no longer use decorators now; use this
makeAutoObservable - No need for a global provider
- The Taro official site and examples are arguably the biggest trap in history. Don't get fooled. URL: https://taro-docs.jd.com/taro/docs/mobx/
- Please use the latest versions of MobX and
mobx-react-lite. Don't use the 4.8 version on the Taro official site—it's too old and useless
Code
No need to wrap with a global provider anymore. Just use a global variable. Of course you can also use React Context.
Store definition
import {makeAutoObservable} from "mobx";
import {User} from "@/models/user";
import * as auth from '@/utils/auth'
export class UserStore {
isLogin = false
user: User | null = null
token = ''
constructor() {
makeAutoObservable(this)
}
login(user: User, token: string) {
this.user = user
this.token = token
this.isLogin = true
// 保存登录数据到本地
auth.login(token, user.username)
}
logout() {
this.isLogin = false
this.user = null
this.token = ''
auth.logout()
}
}
export const myUserStore = new UserStore()
Component usage
import {View} from "@tarojs/components"
import {AtButton} from "taro-ui";
import {observer} from "mobx-react-lite";
import {myUserStore} from "@/store/user";
import Taro from "@tarojs/taro";
import {useEffect} from "react";
export const UserPage = observer(() => {
useEffect(() => {
if (!myUserStore.isLogin) {
Taro.redirectTo({url: '/pages/user/login'})
}
}, [])
return (
<View className='py-3 px-2'>
<View className='at-article__h1'>用户中心</View>
<View className='at-article__h3 mt-1'>用户名:{myUserStore.user?.first_name}</View>
<AtButton className='mt-3' onClick={logout}>退出登录</AtButton>
</View>
)
function logout() {
myUserStore.logout()
Taro.reLaunch({url: '/pages/index/index'})
}
})
export default UserPage
References
- Official docs: https://mobx.js.org/react-integration.html
- Project URL: https://github.com/mobxjs/mobx/tree/main/packages/mobx-react
- MobX React Beginner's Guide (Juejin): https://juejin.cn/post/6844903831726211079
- Using MobX in React with class components, function components, and hooks: https://juejin.cn/post/6873794258743066632#heading-2
Deserializing JSON to a Class
Use this library: https://github.com/typestack/class-transformer
Model definition. This definition can be generated from JSON. There are many online tools, for example: https://apihelper.jccore.cn/jsontool
export class User {
username: string
first_name: string
last_name: string
email: string
date_joined: string
}
Note that the docs on the project homepage are also outdated. The plainToClass method is deprecated; you need to use this method: plainToInstance
import {plainToInstance} from "class-transformer";
const user = plainToInstance(User, res.data.user)
myUserStore.login(user, res.data.token)
_EOF_
Notes on React + TypeScript + Taro Frontend Development
- 本文作者:
- 程序设计实验室
- 版权声明:
- 本博客所有文章除特别声明外,均采用 BY-NC-SA 许可协议。转载请注明出处!
相关文章
使用 swagger-typescript-api 在前端项目里生成请求代码
swagger-typescript-api?文档写得像草稿,还得自己摸索。那些花哨的模块化选项除了报错还能干嘛?老老实实生成单文件,配个客户端封装,省得每次折腾。
2025-11-03 · Web前端 · 约 1 分钟
2025年底的 TailwindCSS 组件库简单横评
TailwindCSS组件库多到让人选择困难。shadcn/ui虽优雅但不够全,Origin UI倒是堆了500+组件——这年头连UI都要内卷?大而全还是小而精,选型前先想清楚自己要不要加班调样式。
2025-11-23 · Web前端 · 约 1 分钟
在网页中使用Material-Design图标
什么是Material Design图标 MD大家都听过的吧,就是谷歌的Material Design设计,Material Design图标就是符合 MD设计语言的图标。 本文通过字体的方法在网页中显示Material Design图标。 What are material icons Material design system icons are simple, modern, friend
2021-12-18 · Web前端 · 约 1 分钟
使用JS模拟按键输入的踩坑记录
坑 一开始在Google搜索了一番,找到了用jQuery的方案,代码量很少,看起来很美好很不错,结果,根本没用…… 我反复试了这几个版本: var e = $.Event('keyup') e.keyCode = 49 $('#btn').trigger(e) // 就是把 keycode 换成 which $('#btn').trigger($.Event('keyup', { which: 4
2021-12-18 · Web前端 · 约 1 分钟
讨论
共 0 条加载评论中…