获取数据的API并将结果导出到另一个组件。

huangapple go评论60阅读模式
英文:

Fetch data API and export result into another component

问题

以下是您提供的代码的中文翻译:

我在使用React Native时是新手我试图从一个API中获取JSON数据然后将其导出到一个Context中以便在Provider中使用它当我在一个列表组件中导入获取数据的文件时一切都正常但当我在Context中导入它时却收到一个空数组可能是因为在完成获取结果之前导出了数据

我该如何导出数据以便将其放入Provider中使得状态对需要此信息的应用程序部分可用

我已经尝试过使用useEffectasync/awaitpromise等使用我在互联网上找到的示例但我没有成功

获取文件

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))

  }, []);
  
  return {
    data
  }

}

Context文件

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

const { data } = getAllProducts() // console.log(data) 结果: 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() // 这里的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>
    )
}
英文:

I'm new in react native, and i'm trying to capture json data from an API, and then exporting it to a Context to be able to use it in a Provider, when I import the file that fetchs, in a list component for example, everything happens normally, but when I import it in the Context , an empty array arrives, probably because it was exporting the data before finalizing the fetch result.

How can I export the data so that I can put it in the providers to make the state available to the part of the application that needs this information?

I already tried using useEffect , async / await , promise, with the examples I found on the internet, but I was unsuccessful

Fetch file

import React, { useState, useEffect } from &#39;react&#39;;
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 = () =&gt; {
const [data, setData] = useState([]);
const url = &quot;https://dummyjson.com/products&quot;
useEffect(() =&gt; {
fetch(url)
.then((resp) =&gt; resp.json())
.then((json) =&gt; setData(json.products))
.catch((error) =&gt; console.error(error))
}, []);
// result of console.log = 
// LOG  Running &quot;rncrud&quot; with {&quot;rootTag&quot;:241}
// LOG  []
// LOG  []
// LOG  [{&quot;brand&quot;: &quot;Apple&quot;, &quot;category&quot;: &quot;smartphones&quot;, &quot;description&quot;..........]}
return {
data
}
}

Context file :

import React, { createContext, useReducer } from &#39;react&#39;
import { getAllProducts, Products } from &#39;../data/products&#39;
const { data } = getAllProducts() // console.log(data) result : data = []
const initialState = { data }
const ProductsContext = createContext({})
type State = {
products: [Products[&#39;item&#39;]]
};
type Actions = {
type: string,
payload: Products[&#39;item&#39;],
}
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 =&gt; u.id === updated.id ? updated : u)
}
},
deleteProduct(state: State, action: Actions) {
const product = action.payload
return {
...state,
products: state.products.filter((prod: { id: number }) =&gt; prod.id !== product.id)
}
}
}
export const ProductsProvider = (props: any) =&gt; {
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 (
&lt;ProductsContext.Provider value={{ state, dispatch }}&gt;
{props.children}
&lt;/ProductsContext.Provider&gt;
)
}
export default ProductsContext

List file where it works

import React, { useContext } from &#39;react&#39;
import { View, FlatList } from &#39;react-native&#39;
import { getAllProducts, Products } from &#39;../data/products&#39;
import ProductCard from &#39;../components/ProductCard&#39;;
import ProductsContext from &#39;../context/ProductContext&#39;;
const numColumns = 2
const isAdmin: boolean = true
export default (props: any) =&gt; {
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 (
&lt;ProductCard
product={{ prod }}
navigation={{ nav }}
isAdmin={isAdmin}
/&gt;
)
}
return (
&lt;View&gt;
&lt;FlatList
numColumns={numColumns}
keyExtractor={p =&gt; `${p[&#39;id&#39;]}`}
data={data}
renderItem={getProductItemCard}
/&gt;
&lt;/View&gt;
)
}

答案1

得分: 1

获取数据 API 并将结果导出到另一个组件

自定义 Hooks

我们可以在组件之外使用 useEffect 创建自定义 Hook,非常简单。

示例

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();

可重复使用的 Hook 函数

  • 请注意,我只展示了 React Web 中的示例,但在 React Native 中也有相同的 Hook 和逻辑。
  • 希望这对你有所帮助。
英文:

Fetch data API and export result into another component

custom Hooks

we can create a custom hook outside of component using useeffect. it is very simple

example

import { useEffect, useState } from &quot;react&quot;;
const url = &quot;https://dummyjson.com/products&quot;;
export const useProducts = () =&gt; {
const [loading, setLoading] = useState(false);
const [products, setProducts] = useState([]);
useEffect(() =&gt; {
fetchProducts();
}, []);
const fetchProducts = async () =&gt; {
try {
setLoading(true);
const res = await fetch(url).then((data) =&gt; data.json());      
setProducts(res.products);
setLoading(false);
} catch (error) {
setLoading(false);
throw new Error(error);
} finally {
setLoading(false);
}
};
return [products, loading];
};

and we can use like

const [products, loading] = useProducts();

reusable hook fun

  • pls note I just show in react web. but there is same hook and login in react native.
  • I hope that can help you

huangapple
  • 本文由 发表于 2023年5月24日 20:20:55
  • 转载请务必保留本文链接:https://go.coder-hub.com/76323473.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定