admin管理员组文章数量:1402786
I'm trying to learn how to use React's Context API as well as Hooks, and trying to work on a project where I'm using fetch().
When using both, I get the request, but I can't get the data I set, except for loading
.
import React,{useState, createContext} from 'react';
export const ProductsContext = createContext();
export const ProductsProvider = props => {
const [categories, setCategories] = useState({ categories: {} });
const [products, setProducts] = useState({ products: {} });
const [loading, setLoading] = useState(true);
useEffect(() => {
(async () => {
const [categoriesResult, productsResult] = await Promise.all([fetch('http://localhost:3000/api/categories'), fetch('http://localhost:3000/api/products')]);
setCategories(categoriesResult);
setProducts(productsResult);
setLoading(false);
})();
}, []);
return (
<ProductsContext.Provider value={ { products, categories, loading } }>
{props.children}
</ProductsContext.Provider>
);
}
Here I'm creating a context where I'd like to pass products (and categories) through the Provider.
import React, { useContext } from 'react';
import { ProductsContext } from './ProductsContext';
const Products = () => {
const {products, categories, loading} = useContext(ProductsContext);
return (
<div className="products">
{ console.log(products, categories, loading) }
</div>
);
};
Page
import React from 'react';
import Header from './Header';
import Banner from './Banner';
import ProductsContainer from './Products/ProductsContainer';
import {ProductsProvider} from './Products/ProductsContext';
const Page = () => (
<>
<Header/>
<Banner/>
<ProductsProvider>
<ProductsContainer/>
</ProductsProvider>
</>
);
export default Page;
This is the results I get via console.log:
{products: {…}} Response {type: "basic", url: "http://localhost:3000/api/categories", redirected: false, status: 200, ok: true, …} true
Products.js:9 Response {type: "basic", url: "http://localhost:3000/api/products", redirected: false, status: 200, ok: true, …} Response {type: "basic", url: "http://localhost:3000/api/categories", redirected: false, status: 200, ok: true, …} true
Products.js:9 Response {type: "basic", url: "http://localhost:3000/api/products", redirected: false, status: 200, ok: true, …} Response {type: "basic", url: "http://localhost:3000/api/categories", redirected: false, status: 200, ok: true, …} false
Products.js:9 Response {type: "basic", url: "http://localhost:3000/api/products", redirected: false, status: 200, ok: true, …} Response {type: "basic", url: "http://localhost:3000/api/categories", redirected: false, status: 200, ok: true, …} false
Products.js:9 Response {type: "basic", url: "http://localhost:3000/api/products", redirected: false, status: 200, ok: true, …} Response {type: "basic", url: "http://localhost:3000/api/categories", redirected: false, status: 200, ok: true, …} false
Products.js:9 Response {type: "basic", url: "http://localhost:3000/api/products", redirected: false, status: 200, ok: true, …} Response {type: "basic", url: "http://localhost:3000/api/categories", redirected: false, status: 200, ok: true, …} false
As you can see, there is no data, but loading changes.
What am I doing wrong? How can I pass products via Context API?
I'm trying to learn how to use React's Context API as well as Hooks, and trying to work on a project where I'm using fetch().
When using both, I get the request, but I can't get the data I set, except for loading
.
import React,{useState, createContext} from 'react';
export const ProductsContext = createContext();
export const ProductsProvider = props => {
const [categories, setCategories] = useState({ categories: {} });
const [products, setProducts] = useState({ products: {} });
const [loading, setLoading] = useState(true);
useEffect(() => {
(async () => {
const [categoriesResult, productsResult] = await Promise.all([fetch('http://localhost:3000/api/categories'), fetch('http://localhost:3000/api/products')]);
setCategories(categoriesResult);
setProducts(productsResult);
setLoading(false);
})();
}, []);
return (
<ProductsContext.Provider value={ { products, categories, loading } }>
{props.children}
</ProductsContext.Provider>
);
}
Here I'm creating a context where I'd like to pass products (and categories) through the Provider.
import React, { useContext } from 'react';
import { ProductsContext } from './ProductsContext';
const Products = () => {
const {products, categories, loading} = useContext(ProductsContext);
return (
<div className="products">
{ console.log(products, categories, loading) }
</div>
);
};
Page
import React from 'react';
import Header from './Header';
import Banner from './Banner';
import ProductsContainer from './Products/ProductsContainer';
import {ProductsProvider} from './Products/ProductsContext';
const Page = () => (
<>
<Header/>
<Banner/>
<ProductsProvider>
<ProductsContainer/>
</ProductsProvider>
</>
);
export default Page;
This is the results I get via console.log:
{products: {…}} Response {type: "basic", url: "http://localhost:3000/api/categories", redirected: false, status: 200, ok: true, …} true
Products.js:9 Response {type: "basic", url: "http://localhost:3000/api/products", redirected: false, status: 200, ok: true, …} Response {type: "basic", url: "http://localhost:3000/api/categories", redirected: false, status: 200, ok: true, …} true
Products.js:9 Response {type: "basic", url: "http://localhost:3000/api/products", redirected: false, status: 200, ok: true, …} Response {type: "basic", url: "http://localhost:3000/api/categories", redirected: false, status: 200, ok: true, …} false
Products.js:9 Response {type: "basic", url: "http://localhost:3000/api/products", redirected: false, status: 200, ok: true, …} Response {type: "basic", url: "http://localhost:3000/api/categories", redirected: false, status: 200, ok: true, …} false
Products.js:9 Response {type: "basic", url: "http://localhost:3000/api/products", redirected: false, status: 200, ok: true, …} Response {type: "basic", url: "http://localhost:3000/api/categories", redirected: false, status: 200, ok: true, …} false
Products.js:9 Response {type: "basic", url: "http://localhost:3000/api/products", redirected: false, status: 200, ok: true, …} Response {type: "basic", url: "http://localhost:3000/api/categories", redirected: false, status: 200, ok: true, …} false
As you can see, there is no data, but loading changes.
What am I doing wrong? How can I pass products via Context API?
Share Improve this question asked Sep 8, 2019 at 21:24 kinxkinx 4935 gold badges15 silver badges33 bronze badges1 Answer
Reset to default 4At casual reading, the React.useContext() looks serviceable. The issue I see is that the React state variables, categories
and product
are being set to the Response from fetch()
and according to MDN's fetch() reference, fetch returns a value that resolves from a Promise to a Response, which is not quite what you want.
But this is close! You should do something like
setCategories(categoriesResult.json());
setProducts(productsResult.json());
or figure out another way to massage the Response.Body
into a form that you can manipulate. Check out the API reference for Response
To resolve the promise, you call promise.then(...)
where promise
is the Promise object returned from fetch()
.
To that end, I would suggest separating the two fetches in order to make resolving the promises simple and possibly make other parts of your interface respond sooner (i.e. if one fetch es in before the other, you could render those results even if you don't have the other. Even if you want to wait until both parts are plete, you could make your rendering contingent on loading
's state.)
export const ProductsProvider = props => {
const [loading, setLoading] = useState(true);
const [categories, setCategories] = useState({});
useEffect(() => {
fetch('http://localhost:3000/api/categories')
.then((response) => {
setCategories(response.json());
}
setLoading(/* false only if categories AND product are not {} */);
}, []);
// Repeat the above, except for products
return (
<ProductsContext.Provider value={ { products, categories, loading } }>
{props.children}
</ProductsContext.Provider>
);
}
本文标签: javascriptUsing useEffect and useContext while fetching dataStack Overflow
版权声明:本文标题:javascript - Using useEffect and useContext while fetching data - Stack Overflow 内容由网友自发贡献,该文观点仅代表作者本人, 转载请联系作者并注明出处:http://www.betaflare.com/web/1744348657a2601919.html, 本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌抄袭侵权/违法违规的内容,一经查实,本站将立刻删除。
发表评论