React Native:如何从多个rest api获取后动态渲染多幅图像

问题描述 投票:0回答:1

我无法呈现从React原生的多次调用rest API所获取的多个图像。

有关Rest API的参考,我使用woocommerce rest API来获取订单详细信息。https://woocommerce.github.io/woocommerce-rest-api-docs/#retrieve-an-order

问题在于,订单详细信息在rest API中没有line_items的主图像。因此,我需要调用以下每个产品详细信息API,以通过再次调用产品详细信息其余API通过product_id来获取每个line_item对象的产品图像。

https://woocommerce.github.io/woocommerce-rest-api-docs/#retrieve-a-product

到目前为止,我已经编写了调用每个line_items产品详细信息的逻辑,但是我的代码却出现错误。处理这种情况的最佳方法是什么?

Warning: Cannot update during an existing state transition (such as within `render`). Render methods should be a pure function of props and state.

Maximum update depth exceeded. This can happen when a component repeatedly calls setState inside componentWillUpdate or componentDidUpdate. React limits the number of nested updates to prevent infinite loops.

Warning: Can't perform a React state update on an unmounted component. This is a no-op, but it indicates a memory leak in your application. To fix, cancel all subscriptions and asynchronous tasks in %s.%s, the componentWillUnmount method,

下面是我的实现:

render() {
        if (this.state.loading) {
            return (
                <View style={{ flex: 1, justifyContent: "center", alignContent: "center", padding: 20 }}>
                    <ActivityIndicator color='#96588a' size='large' />
                </View>
            )
        }

        return (
            <ScrollView style={{ flex: 1 }}>
                {this.displayOrderDataSection()}
                {this.displayProductSection()}
                {this.displayPaymentSection()}
                {this.displayShippingDetailsSection()}
                {this.displayBillingDetailsSection()}
            </ScrollView>
        );
    }

    getProductPrimaryImage = (productId) => {
        let productData = null;
        this.setState({ imageLoading: true });
        let url = `${base_url}/wp-json/wc/v3/products/${productId}?consumer_key=${c_key}&consumer_secret=${c_secret}`
        console.log(url);
        fetch(url)
            .then((response) => response.json())
            .then((responseJson) => {
                this.setState({
                    imageLoading: false,
                    error: responseJson.code || null,
                });
                productData = responseJson
            })
            .then(() => {
                return productData ?
                    ((Array.isArray(productData.images) && productData.images.length) ?
                        productData.images[0].src : null)
                    : null;

            })
            .catch((error) => {
                this.setState({
                    error,
                    imageLoading: false,
                })
            });
    }

    getLineItems = () => {
        let itemArray = [];
        orderData.line_items.forEach(item => {
            let imgSrc = this.getProductPrimaryImage(item.product_id)
            itemArray.push(
                <View key={item.id} style={{ flex: 1, flexDirection: 'row', backgroundColor: 'white' }}>
                    <View style={{ flex: 1, justifyContent: "center", alignContent: "center" }}>
                        <Image source={imgSrc}
                            style={{ height: 100, width: 100 }} resizeMode='contain' />
                    </View>
                    <View style={{ flex: 2, marginTop: 10, marginBottom: 10, justifyContent: "center" }}>
                        <View style={{ marginLeft: 10 }}>
                            <Text>{item.name}</Text>
                            <Text>SKU: {item.sku}</Text>
                            <Text>Price: {this.getCurrencySymbol()}{item.price.toFixed(2)}</Text>
                            <Text>Oty: {item.quantity}</Text>
                            <View>{this.getTMProductOptions(item.meta_data)}</View>
                        </View>
                    </View>
                </View>
            )
        })
        return itemArray;
    }

    displayProductSection = () => {
        return (
            <View style={styles.section}>
                <Text style={styles.titleText}>Product</Text>
                {this.getLineItems()}
            </View>
        )
    }

reactjs rest react-native woocommerce woocommerce-rest-api
1个回答
0
投票

考虑render()方法的方法是它可以重复运行。在大多数情况下,每当有更改影响其输出时,它都会重新运行。

您的结构化方式,您的render()函数调用{this.displayProductSection()},后者调用this.getLineItems(),后者调用this.getProductPrimaryImage(item.product_id),这向WordPress API发出AJAX请求。

由于渲染可以(并且很可能会)重复运行,这意味着您对图像的请求正在重复创建。

运行AJAX请求与显示图像一样,[,将src URL放在标记中,浏览器将其加载一次。 HTML被解析并运行一次,这是重复请求它。

更好的模式是:

    处于状态,跟踪是否已请求远程数据。您可以通过初始化,加载,成功,错误等可能的字符串来创建状态属性。
  • 在您的componentDidMount中,请求数据。将状态从init更改为loading。
  • 当输入数据时,将状态从加载更改为成功(或错误,取决于结果),并将结果存储在状态中。
  • 在渲染函数中,根据该status属性执行条件。如果正在加载,请显示加载器。如果成功,则根据您上面存储的状态输出图像。
  • 有时,在装入组件时,您还没有准备好获取远程数据。也许这首先取决于某些用户输入。在这种情况下,您可以改用componentDidUpdate。检查那里的条件,但是由于

    this

  • 函数调用也反复运行,因此也请检查状态并仅在尚未请求时才请求状态。
    © www.soinside.com 2019 - 2024. All rights reserved.