【问题标题】:React componentDidMount not firing and not updating state in electron appReact componentDidMount未触发且未更新电子应用程序中的状态
【发布时间】:2020-04-22 00:44:53
【问题描述】:

我正在创建一个电子反应应用程序,我正在使用这个样板文件https://github.com/willjw3/react-electron

我正在尝试从 API 获取数据,我能够获取数据但无法使用 setState 更新状态。 componentDidMount 也没有触发。我设置错了吗?这是我的代码。

import React from "react"
import '../css/table.css'

const fs = window.require('fs');
const electron = window.require('electron')
const shell = electron.shell
const stockxAPI = window.require('stockx-api');
const stockX = new stockxAPI();

const scrapeStockx = (link, size) => {
    let lowestAsk 
    return stockX.fetchProductDetails(link)
        .then((response) => {
            let productData = response.variants
            //console.log(productData)
            for (let product of productData){
                if (product.size == size){
                    lowestAsk = product.market.lowestAsk
                    return '$' + lowestAsk
                }
            } 
    })
}
const fetchNewData = async (myProducts) => {
    for (let product of myProducts){
        let goatUrl = 'https://www.goat.com/web-api/v1/product_variants?productTemplateId='
        let goatSKU = product.Goat[0].split('sneakers/')[1]
        let ogUrl = goatUrl + goatSKU

        let price = await scrapeStockx(product.Stockx[0], product.Size)
        product.Stockx[1] = price
        console.log('Product Size: ' + product.Stockx[1])
    }
    return myProducts
}

class ProductTable extends React.Component{
    constructor(){
        super()
        this.state = {
            Products : ''
        }
        this.renderTableData = this.renderTableData.bind(this)
        this.updateProducts = this.updateProducts.bind(this)
    }

    async componentDidMount(){
        this.setState({Products : 'Loading...'});
        let myProducts = await this.updateProducts()
        console.log('Component ' + myProducts)
        this.setState({Products : myProducts})
        console.log('Component' + this.state)
    }


    async updateProducts () {
        let rawData = fs.readFileSync('/Users/yunioraguirre/Desktop/Lucky Cops Item Tracker V1/Lucky Item Tracker/MyProducts.json')
        let myProducts = JSON.parse(rawData)

        //Updates Goat and Stockx Prices
        myProducts = await fetchNewData(myProducts)
        try {
            await fs.writeFileSync('MyProducts.json', JSON.stringify(myProducts, null, 2))
            console.log('Success!')
            console.log(myProducts)
        } catch (error) {
            console.log(error)
        }
        return myProducts
    }

    renderTableData = () => {
        return this.state.Products.map( product => {
            const {Id, Item, sku, Size, Sold, Goat, Stockx} = product
            return (
                <tr key={Id}>
                    <td>{Id}</td>
                    <td>{Item}</td>
                    <td>{sku}</td>
                    <td>{Size}</td>
                    <td>{product["Total Amount Paid"]}</td>
                    <td>{Sold}</td>
                    <td>{product['Price Sold For']}</td>
                    <td> <a href={Goat[0]} target='_blank' rel="noopener noreferrer">{Goat[1]}</a></td>
                    <td> <a href={Stockx[0]} target='_blank' rel="noopener noreferrer">{Stockx[1]}</a></td>
                    <td> <a href={product['Flight Club'][0]} target="_blank" rel="noopener noreferrer">{product['Flight Club']}</a></td>
                </tr>
            )
        })
    }

    renderTableHeader = () => {
        console.log('State in Render' + JSON.stringify(this.state.Products))
        let header = Object.keys(this.state.Products[0])
        return header.map((key, index) => {
            return <th key={index}>{key.toUpperCase()}</th>
        })
    }
    render(){
        return (
            <div id='Table-Wrapper'>
                <h1 id='TableTitle'>Total Products</h1>
                <table id='Products Table'>
                    <tbody>
                        <tr>{this.renderTableHeader()}</tr>
                        {this.renderTableData()}
                    </tbody>
                </table>
            </div>
        )
    }


}

export default ProductTable

这是我在控制台中得到的

【问题讨论】:

    标签: javascript reactjs electron


    【解决方案1】:

    问题是您提供了一个空字符串作为初始状态。第一个控制台日志来自render 函数,第二个来自this.renderTableHeader。当您点击此行时会出现问题:let header = Object.keys(this.state.Products[0])

    Object.keys(""[0])

    您可能想尝试创建一个单独的“isLoading”状态,并在其上有条件地渲染 JSX。

    this.state = {
      Products : '',
      isLoading: false,
    }
    
    ...
    
    async componentDidMount(){
      this.setState({isLoading: true});
      let myProducts = await this.updateProducts()
      console.log('Component ' + myProducts)
      this.setState({Products: myProducts, isLoading: false})
    }
    
    ....
    
    render(){
      if (this.state.isLoading) {
        return <div>Loading...</div>;
      }
    
      return (
        <div id='Table-Wrapper'>
          <h1 id='TableTitle'>Total Products</h1>
          <table id='Products Table'>
            <tbody>
              <tr>{this.renderTableHeader()}</tr>
              {this.renderTableData()}
            </tbody>
          </table>
        </div>
      )
    }
    

    【讨论】:

    • 嗨,我修复了我的代码,但我仍然遇到同样的错误,ComponentDidMount 没有触发,因为我在控制台中看不到 console.log
    • 我在 componentDidMount 中将我的 isLoading 更改为 True 并将 isLoading 更改为 False 并且它似乎触发但现在我收到一个新错误 Warning: can't perform a React state update on 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 the componentWillUnmount method.
    • @NinoSoles 这实际上只是一个警告,是一个单独的不相关问题。 一些调用updateProducts 似乎已经进行并且在ProductTable 卸载时仍在进行中。正如警告所暗示的那样,任何异步更新组件状态的函数都需要能够在组件卸载时取消更新。您可以使用带有 fetch 请求的中止控制器,并在 componentWillUnmount 中中止它。
    【解决方案2】:

    我能够修复我的代码。正如 Drew 所说,我需要一个处于状态的 isLoading 变量,以便我可以渲染和获取我的数据。这是我更新的 State 和 ComponentDidMount

    class ProductTable extends React.Component{
        constructor(){
            super()
            this.state = {
                Products : '',
                isLoading : true
            }
            this.renderTableData = this.renderTableData.bind(this)
            this.updateProducts = this.updateProducts.bind(this)
        }
    
        async componentDidMount(){
            let myProducts = await this.updateProducts()
            console.log('Component ' + JSON.stringify(myProducts))
            console.log('\n')
            await this.setState({Products : myProducts, isLoading : false})
            //console.log(JSON.stringify(this.state))
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2018-09-20
      • 2017-04-25
      • 2020-11-06
      • 2020-08-16
      • 2016-03-01
      • 1970-01-01
      • 1970-01-01
      • 2021-03-29
      • 2015-06-11
      相关资源
      最近更新 更多