React Native 获取数据API并将结果导出到其他组件

e0bqpujr  于 2023-05-29  发布在  React
关注(0)|答案(1)|浏览(190)

我是react native的新手,我试图从API中捕获json数据,然后将其导出到Context以便能够在Provider中使用它,当我导入提取的文件时,例如在列表组件中,一切正常,但当我将其导入Context时,到达一个空数组,可能是因为它在最终确定提取结果之前导出数据。
如何导出数据,以便将其放入提供程序中,从而使需要此信息的应用程序部分可以使用状态?
我已经试过使用useEffect、async / await、promise,并在网上找到了一些例子,但是没有成功
取文件

import React, { useState, useEffect } from 'react';

export type Products = {
  item: {
    id: number,
    title: string,
    description: string,
    price: number,
    discountPercentage: number,
    rating: number,
    stock: number,
    brand: string,
    category: string,
    thumbnail: string,
    images: []
  }
}

export const getAllProducts = () => {
  
  const [data, setData] = useState([]);
  const url = "https://dummyjson.com/products"

  useEffect(() => {
    fetch(url)
      .then((resp) => resp.json())
      .then((json) => setData(json.products))
      .catch((error) => console.error(error))

  }, []);
  // result of console.log = 
  // LOG  Running "rncrud" with {"rootTag":241}
  // LOG  []
  // LOG  []
  // LOG  [{"brand": "Apple", "category": "smartphones", "description"..........]}

  return {
    data
  }

}

上下文文件:

import React, { createContext, useReducer } from 'react'
import { getAllProducts, Products } from '../data/products'

const { data } = getAllProducts() // console.log(data) result : data = []

const initialState = { data }
const ProductsContext = createContext({})

type State = {
    products: [Products['item']]
};

type Actions = {
    type: string,
    payload: Products['item'],
}

const actions: any = {
    createProduct(state: State, action: Actions) {
        const product = action.payload
        product.id = Math.random()
        return {
            ...state,
            products: [...state.products, product]
        }
    },

    updateProduct(state: State, action: Actions) {
        const updated = action.payload
        return {
            ...state,
            products: state.products.map(u => u.id === updated.id ? updated : u)
        }
    },

    deleteProduct(state: State, action: Actions) {
        const product = action.payload
        return {
            ...state,
            products: state.products.filter((prod: { id: number }) => prod.id !== product.id)
        }
    }
}

export const ProductsProvider = (props: any) => {

    function reducer(state: any, action: Actions) {
        const fn: any = actions[action.type]
        return fn ? fn(state, action) : state

    }

    const [state, dispatch] = useReducer(reducer, initialState)

    return (
        <ProductsContext.Provider value={{ state, dispatch }}>
            {props.children}
        </ProductsContext.Provider>
    )
}

export default ProductsContext

列出文件的工作位置

import React, { useContext } from 'react'
import { View, FlatList } from 'react-native'
import { getAllProducts, Products } from '../data/products'
import ProductCard from '../components/ProductCard';
import ProductsContext from '../context/ProductContext';

const numColumns = 2

const isAdmin: boolean = true

export default (props: any) => {

    const { data } = getAllProducts() // here data is an array of objects with data
    
    //const { state, dispatch }: any = useContext(ProductsContext)

    function getProductItemCard({ item: prod }: Products) {

        const nav = props.navigation

        return (
            <ProductCard
                product={{ prod }}
                navigation={{ nav }}
                isAdmin={isAdmin}
            />
        )
    }

    return (
        <View>
            <FlatList
                numColumns={numColumns}
                keyExtractor={p => `${p['id']}`}
                data={data}
                renderItem={getProductItemCard}
            />
        </View>
    )
}
qxgroojn

qxgroojn1#

获取数据API,并将结果导出到其他组件
自定义钩子

我们可以使用useeffect在组件外部创建一个自定义钩子。很简单
example

import { useEffect, useState } from "react";
const url = "https://dummyjson.com/products";

export const useProducts = () => {
  const [loading, setLoading] = useState(false);
  const [products, setProducts] = useState([]);
  useEffect(() => {
    fetchProducts();
  }, []);
  const fetchProducts = async () => {
    try {
      setLoading(true);
      const res = await fetch(url).then((data) => data.json());      
      setProducts(res.products);
      setLoading(false);
    } catch (error) {
      setLoading(false);
      throw new Error(error);
    } finally {
      setLoading(false);
    }
  };
  return [products, loading];
};

我们可以用

const [products, loading] = useProducts();

可重复使用的钩子

  • 请注意,我只是显示在React网络。但是在react native中有相同的hook和login。
  • 希望能帮到你

相关问题