在获取数据时使用 useEffect 和 useContext
Using useEffect and useContext while fetching data
我正在尝试学习如何使用 React 的上下文 API 以及 Hooks,并尝试在我使用 fetch() 的项目上工作。
同时使用两者时,我得到了请求,但我无法获取我设置的数据,除了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>
);
}
我在这里创建了一个上下文,我想在其中通过提供商传递产品(和类别)。
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>
);
};
页
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;
这是我通过 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
如您所见,没有数据,但正在加载变化。
我做错了什么?如何通过 Context API?
传递产品
在随意阅读时,React.useContext() 看起来很有用。我看到的问题是 React 状态变量 categories
和 product
被设置为来自 fetch()
的响应并根据 MDN's fetch() reference,获取 returns a从 Promise 解析为 Response 的值,这不是您想要的。
但这已经很接近了!你应该做类似
setCategories(categoriesResult.json());
setProducts(productsResult.json());
或者找出另一种方法将 Response.Body
按摩成您可以操纵的形式。 Check out the API reference for Response
要解决承诺,您调用 promise.then(...)
,其中 promise
是从 fetch()
.
返回的 Promise 对象
为此,我建议将两个提取分开,以便使解决承诺变得简单,并可能使界面的其他部分响应更快(即,如果一个提取先于另一个提取,则可以呈现这些结果即使你没有另一个。即使你想等到两个部分都完成,你也可以让你的渲染取决于 loading
的状态。)
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>
);
}
我正在尝试学习如何使用 React 的上下文 API 以及 Hooks,并尝试在我使用 fetch() 的项目上工作。
同时使用两者时,我得到了请求,但我无法获取我设置的数据,除了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>
);
}
我在这里创建了一个上下文,我想在其中通过提供商传递产品(和类别)。
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>
);
};
页
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;
这是我通过 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
如您所见,没有数据,但正在加载变化。
我做错了什么?如何通过 Context API?
传递产品在随意阅读时,React.useContext() 看起来很有用。我看到的问题是 React 状态变量 categories
和 product
被设置为来自 fetch()
的响应并根据 MDN's fetch() reference,获取 returns a从 Promise 解析为 Response 的值,这不是您想要的。
但这已经很接近了!你应该做类似
setCategories(categoriesResult.json());
setProducts(productsResult.json());
或者找出另一种方法将 Response.Body
按摩成您可以操纵的形式。 Check out the API reference for Response
要解决承诺,您调用 promise.then(...)
,其中 promise
是从 fetch()
.
为此,我建议将两个提取分开,以便使解决承诺变得简单,并可能使界面的其他部分响应更快(即,如果一个提取先于另一个提取,则可以呈现这些结果即使你没有另一个。即使你想等到两个部分都完成,你也可以让你的渲染取决于 loading
的状态。)
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>
);
}