Skip to content

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 axios
npm install axios
tsx
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-storage
npm install @react-native-async-storage/async-storage
tsx
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-redux
npm install @reduxjs/toolkit react-redux
tsx
// 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 zustand
npm install zustand
tsx
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>
}