简体   繁体   English

如何将数据传输到另一个组件(useEffect 问题)

[英]how can I transfer the data to another component (useEffect problem)

In useEffect, I retrieve the data from the server and store it in the "products" array:在 useEffect 中,我从服务器检索数据并将其存储在“products”数组中:

const { url } = props;
const [products, setProducts] = useState([]);

  useEffect(() => {
    const fetchProducts = async () => {
      setLoadingSpinner(true);
      const response = await fetch(url);
      const responseData = await response.json();
      setLoadingSpinner(false);
      const loadedProducts = [];

      for (const key in responseData) {
        loadedProducts.push({
          id: key,
          name: responseData[key].name,
          description: responseData[key].description,
          price: responseData[key].price,
          image: responseData[key].image,
          processor: responseData[key].processor,
        });
      }
      setProducts(loadedProducts);
      setIsDataLoaded(true);
    };
    fetchProducts();
  }, [url, isDataLoaded]);

I pass it to the ProductDetail component:我将它传递给 ProductDetail 组件:

<ProductDetail products={products}></ProductDetail>

I always get a null value in the ProductDetail component:我总是在 ProductDetail 组件中得到一个 null 值:

function ProductDetail(props) {
    const params = useParams();
    const [product, setProduct] = useState(null);
    
    useEffect(() => {
      if (props.products && params.productId) {
        const product = props.products.find(product => product.id === params.productId);
        setProduct(product);
      }
    }, [props.products, params.productId]);

    console.log(product)

I realized that when useEffect is run for the first time, my "products" array is still empty and it sends it to the component, so it's not good.我意识到当 useEffect 第一次运行时,我的“products”数组仍然是空的,它会将它发送到组件,所以这并不好。 But I don't know how to fix this.但我不知道如何解决这个问题。

There are a couple of things wrong here.这里有一些错误。 I'm going to start with something that seems tangential at first but it will lead to a better answer.我将从一开始看起来切线的东西开始,但它会导致更好的答案。

In ProductDetail you introduce a new state called product .ProductDetail中,您引入了一个名为product的新 state。 You then, in a useEffect , find the product from the list & product id in props and set this back into the state item.然后,在useEffect中,从 props 中的列表和产品 ID 中找到产品,并将其设置回 state 项目。 This would be unnecessary state duplication (even if not copying a prop verbatim into state, a value derived directly from props still counts) and is going to increase the surface areas for bugs in your application (this is probably the most common beginner's error).这将是不必要的 state 重复(即使没有将 prop 逐字复制到 state,直接从 props 派生的值仍然很重要)并且会增加应用程序中错误的表面积(这可能是最常见的初学者错误)。

You actually don't need that state item, you just need useMemo :你实际上不需要那个 state 项目,你只需要useMemo

function ProductDetail(props) {
    const params = useParams();
    
    const product = useMemo(() => {
      if (props.products && params.productId) {
        return props.products.find(product => product.id === params.productId);
      }
    }, [props.products, params.productId]);

    console.log(product)

To solve the issue with the product not being found briefly whilst then products load you can either (a) conditionally render the component so this code doesn't even run in the first place when products isn't fetched yet.要解决在加载产品时暂时找不到产品的问题,您可以 (a) 有条件地呈现组件,这样当尚未获取products时,此代码甚至不会首先运行。 Or (b) Change the ProductDetail so that it effectively does nothing until the product is found.或者 (b) 更改ProductDetail ,使其在找到产品之前什么都不做。

Solution A溶液A

const [products, setProducts] = useState(null); // We change the default to null to be able to distinguish empty list case from loading case.

// ...

{products !== null && <ProductDetail products={products}></ProductDetail>}

Solution B溶液B

function ProductDetail(props) {
    const params = useParams();
    
    const product = useMemo(() => {
      if (props.products && params.productId) {
        return props.products.find(product => product.id === params.productId);
      }
    }, [props.products, params.productId]);

    if (!product) return null // Return early (do nothing) whilst product is not found

    // ... your original render contents

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM