ReactNative 数据与存储
网络请求
fetch
React Native 内置 fetch API,用法与 Web 一致:
tsx
// GET 请求
async function getPosts() {
try {
const response = await fetch('https://api.example.com/posts')
const data = await response.json()
return data
} catch (error) {
console.error('请求失败', error)
}
}
// POST 请求
async function createPost(title: string) {
const response = await fetch('https://api.example.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer token',
},
body: JSON.stringify({ title, body: 'content' }),
})
return response.json()
}// GET 请求
async function getPosts() {
try {
const response = await fetch('https://api.example.com/posts')
const data = await response.json()
return data
} catch (error) {
console.error('请求失败', error)
}
}
// POST 请求
async function createPost(title: string) {
const response = await fetch('https://api.example.com/posts', {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: 'Bearer token',
},
body: JSON.stringify({ title, body: 'content' }),
})
return response.json()
}axios
第三方网络库,功能更丰富:
bash
npm install axiosnpm install axiostsx
import axios from 'axios'
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000,
headers: { Authorization: 'Bearer token' },
})
// 请求拦截器
api.interceptors.request.use(
config => {
// 添加 token 等
return config
},
error => Promise.reject(error)
)
// 响应拦截器
api.interceptors.response.use(
response => response.data,
error => {
if (error.response?.status === 401) {
// 跳转登录
}
return Promise.reject(error)
}
)
// 使用
async function getData() {
const data = await api.get('/posts')
const result = await api.post('/posts', { title: '新文章' })
}import axios from 'axios'
const api = axios.create({
baseURL: 'https://api.example.com',
timeout: 10000,
headers: { Authorization: 'Bearer token' },
})
// 请求拦截器
api.interceptors.request.use(
config => {
// 添加 token 等
return config
},
error => Promise.reject(error)
)
// 响应拦截器
api.interceptors.response.use(
response => response.data,
error => {
if (error.response?.status === 401) {
// 跳转登录
}
return Promise.reject(error)
}
)
// 使用
async function getData() {
const data = await api.get('/posts')
const result = await api.post('/posts', { title: '新文章' })
}网络状态监听
tsx
import NetInfo from '@react-native-community/netinfo'
// 获取当前网络状态
const state = await NetInfo.fetch()
console.log('网络类型:', state.type)
console.log('是否在线:', state.isConnected)
// 监听网络变化
const unsubscribe = NetInfo.addEventListener(state => {
if (!state.isConnected) {
Alert.alert('网络已断开')
}
})
// 取消监听
unsubscribe()import NetInfo from '@react-native-community/netinfo'
// 获取当前网络状态
const state = await NetInfo.fetch()
console.log('网络类型:', state.type)
console.log('是否在线:', state.isConnected)
// 监听网络变化
const unsubscribe = NetInfo.addEventListener(state => {
if (!state.isConnected) {
Alert.alert('网络已断开')
}
})
// 取消监听
unsubscribe()AsyncStorage
本地持久化存储(类似 Web 的 localStorage):
bash
npm install @react-native-async-storage/async-storagenpm install @react-native-async-storage/async-storagetsx
import AsyncStorage from '@react-native-async-storage/async-storage'
// 存储
await AsyncStorage.setItem('token', 'abc123')
await AsyncStorage.setItem('user', JSON.stringify({ id: 1, name: 'Tom' }))
// 读取
const token = await AsyncStorage.getItem('token')
const user = JSON.parse(await AsyncStorage.getItem('user') || '{}')
// 删除
await AsyncStorage.removeItem('token')
// 清空
await AsyncStorage.clear()import AsyncStorage from '@react-native-async-storage/async-storage'
// 存储
await AsyncStorage.setItem('token', 'abc123')
await AsyncStorage.setItem('user', JSON.stringify({ id: 1, name: 'Tom' }))
// 读取
const token = await AsyncStorage.getItem('token')
const user = JSON.parse(await AsyncStorage.getItem('user') || '{}')
// 删除
await AsyncStorage.removeItem('token')
// 清空
await AsyncStorage.clear()封装工具
tsx
// utils/storage.ts
const Storage = {
async get<T>(key: string): Promise<T | null> {
const value = await AsyncStorage.getItem(key)
return value ? JSON.parse(value) : null
},
async set(key: string, value: any): Promise<void> {
await AsyncStorage.setItem(key, JSON.stringify(value))
},
async remove(key: string): Promise<void> {
await AsyncStorage.removeItem(key)
},
}
export default Storage// utils/storage.ts
const Storage = {
async get<T>(key: string): Promise<T | null> {
const value = await AsyncStorage.getItem(key)
return value ? JSON.parse(value) : null
},
async set(key: string, value: any): Promise<void> {
await AsyncStorage.setItem(key, JSON.stringify(value))
},
async remove(key: string): Promise<void> {
await AsyncStorage.removeItem(key)
},
}
export default Storage状态管理
React Context + useReducer
适合中小型应用:
tsx
// contexts/AuthContext.tsx
const AuthContext = createContext(null)
function AuthProvider({ children }) {
const [state, dispatch] = useReducer(authReducer, {
user: null,
token: null,
})
return (
<AuthContext.Provider value={{ state, dispatch }}>
{children}
</AuthContext.Provider>
)
}
// 使用
function LoginScreen() {
const { dispatch } = useContext(AuthContext)
const login = async () => {
const user = await api.login(values)
dispatch({ type: 'LOGIN', payload: user })
}
}// contexts/AuthContext.tsx
const AuthContext = createContext(null)
function AuthProvider({ children }) {
const [state, dispatch] = useReducer(authReducer, {
user: null,
token: null,
})
return (
<AuthContext.Provider value={{ state, dispatch }}>
{children}
</AuthContext.Provider>
)
}
// 使用
function LoginScreen() {
const { dispatch } = useContext(AuthContext)
const login = async () => {
const user = await api.login(values)
dispatch({ type: 'LOGIN', payload: user })
}
}Redux Toolkit
适合大型应用:
bash
npm install @reduxjs/toolkit react-reduxnpm install @reduxjs/toolkit react-reduxtsx
// store/slice.ts
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
export const fetchPosts = createAsyncThunk('posts/fetch', async () => {
const response = await fetch('https://api.example.com/posts')
return response.json()
})
const postsSlice = createSlice({
name: 'posts',
initialState: { items: [], loading: false },
reducers: {},
extraReducers: builder => {
builder
.addCase(fetchPosts.pending, state => { state.loading = true })
.addCase(fetchPosts.fulfilled, (state, action) => {
state.loading = false
state.items = action.payload
})
},
})
// 使用
function PostList() {
const dispatch = useDispatch()
const { items, loading } = useSelector(state => state.posts)
useEffect(() => {
dispatch(fetchPosts())
}, [])
}// store/slice.ts
import { createSlice, createAsyncThunk } from '@reduxjs/toolkit'
export const fetchPosts = createAsyncThunk('posts/fetch', async () => {
const response = await fetch('https://api.example.com/posts')
return response.json()
})
const postsSlice = createSlice({
name: 'posts',
initialState: { items: [], loading: false },
reducers: {},
extraReducers: builder => {
builder
.addCase(fetchPosts.pending, state => { state.loading = true })
.addCase(fetchPosts.fulfilled, (state, action) => {
state.loading = false
state.items = action.payload
})
},
})
// 使用
function PostList() {
const dispatch = useDispatch()
const { items, loading } = useSelector(state => state.posts)
useEffect(() => {
dispatch(fetchPosts())
}, [])
}Zustand
轻量状态管理:
bash
npm install zustandnpm install zustandtsx
import { create } from 'zustand'
const useStore = create(set => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 })),
reset: () => set({ count: 0 }),
}))
// 使用
function Counter() {
const { count, increment } = useStore()
return <Text onPress={increment}>{count}</Text>
}import { create } from 'zustand'
const useStore = create(set => ({
count: 0,
increment: () => set(state => ({ count: state.count + 1 })),
reset: () => set({ count: 0 }),
}))
// 使用
function Counter() {
const { count, increment } = useStore()
return <Text onPress={increment}>{count}</Text>
}
Cao Note