【问题标题】:reactJS and dynamic render and variable populationreactJS 和动态渲染和变量填充
【发布时间】:2019-01-31 22:10:15
【问题描述】:

我想在我的 render() 中动态生成输出,但我遇到了一个非常奇怪的情况。我有一个过程,我使用 fetch() 从数据库中检索一些数据。取回数据后,我确定数据记录的数量,然后执行 for 循环以使用返回的数据填充数组。我在 for 循环之前有一个 console.log() 来显示我的数据接收数组的内容,在我填充接收数组时还有另一个 console.log()。出于某种原因,当我填充数组的特定出现时,数组的所有出现似乎都在变化。这是我拥有的全部代码:

import React from 'react';
import '../styles/app.css';


class testpage extends React.Component {


constructor(props) {
    super(props);
    this.state = {
        productArray: []
    };

}


componentWillMount() {

    var tempData = '';
    var numberOfRecords = 0;

    let url = "http://wmjwwebapi-dev.us-west-2.elasticbeanstalk.com/api/getdata";
    const options = { method: 'GET' };

    fetch(url, options)
    .then(function(response) {
        return response.json();
    })
    .then(function(myJson) {
        if (myJson == undefined) 
        {
            console.log("fetch failed");
        } 
        else 
        {
            //inspect the data that the WebAPI returned 
            var return_code = myJson[0].return_code;
            if (return_code == "Default Return code"){
                tempData = '';
                numberOfRecords = -2;
            } else {
                tempData = JSON.parse(myJson[0].return_string)
                numberOfRecords = tempData.barcode.length;

                var counter = 0;
                var productArray = new Array;
                var product = {
                    barcode: '',
                    name: '',
                    description: '',
                    image: '',
                    price: ''
                }


                for (counter=0;counter<numberOfRecords;counter++) {
                    product.barcode = tempData.barcode[counter];
                    product.name = tempData.name[counter];
                    productArray[counter] = product;
                }                  
            }
        }
    }); 
  }

render() {
    <div>
        <div>
            {this.state.productArray[0].barcode}
        </div>
    </div>
}

}

export default testpage;

当循环计数器 = 0 时,这是我在 console.log() 中看到的图像:

注意到 5000159459228 的条形码值了吗?该值被推入 productArray[0].barcode。这正是我所期望的。

当循环计数器 = 1 时,这是我在 console.log() 中看到的图像: 这里,读取的记录的条形码是 5000159459230。这个值应该进入 productArray1.barcode,如图所示。但是图片也显示productArray[0].barcode的值从5000159459228(第一条记录的值)变成了5000159459230(第二条记录的值)。

这是第三次循环的图像:

再次,barcode = 5000159459231 的新记录。似乎该值被推入 productArray2.barcode 但 productArray[0].barcode 和 productArray1.barcode 现在已更改。

这怎么可能?

最终,目标是动态呈现检索到的数据。

提前感谢您的帮助。

【问题讨论】:

  • 除了这里给出的答案,还要检查这个:stackoverflow.com/questions/11284663/… 以及该问题中的所有其他后续内容:)
  • 我按照您的建议更改了调试输出。结果显示进入我的 for 循环的数组是空的。但是,在我的 for 循环中生成的输出表明,当我将数据添加到 productArray 事件中时,它正在使用相同的数据更改所有先前填充的事件。我已经编辑了我的原始帖子以包含更改的代码和输出。
  • 日志太多,但您在此处描述的内容是正常的,并在其他答案中进行了解释。如果console.log 是唯一的问题,请不要打扰。如果问题是将您的数据正确地反映到 DOM,则更改您的渲染逻辑。就个人而言,我不喜欢 for 循环和直接通过改变对象的属性来更改对象。
  • @devserkan 我将渲染逻辑更改为
    {this.state.productArray[0].barcode}
    并更改了状态的定义从 productArray: '' 到 productArray: [] 的变量,我将 renderELS 更改为 componentWillMount()。现在我收到一个错误,指出 Uncaught (in promise) TypeError: Cannot read property '_currentElement' of null at 。我定义状态变量的方式或尝试在渲染中引用它的方式肯定有一些错误。我想。
  • 我认为您的 API 没有返回健康的响应?我想它不是 JSON,也不是正确的 XML。

标签: reactjs


【解决方案1】:

控制台输出通常可以依赖于原语,但不能依赖于对象。控制台实现特定于执行脚本的环境(浏览器)。

输出的是对象引用,而不是对象快照。当一个对象发生变化时,它在控制台中的表示也会发生变化。

请注意,在 Chrome 控制台中,该数组最初记录为 [] 空数组,而下一个日志条目是 [...] 非空数组。

要输出不追溯更改的对象快照,请使用console.log(JSON.stringify(array)) 或其他序列化的原始值。

【讨论】:

  • 我按照您的建议更改了调试输出。结果显示进入我的for循环的数组是空的。但是,在我的 for 循环中生成的输出表明,当我将数据添加到 productArray 事件中时,它正在使用相同的数据更改所有先前填充的事件。我已经编辑了我的原始帖子以包含更改的代码和输出。
【解决方案2】:

我建议使用 chrome devtools 进行调试,并在数组填充的位置添加断点。
您也可以在代码中的任何位置添加debugger 然后它会提示devtools。 我第二次@estus 关于更改反映在您使用过控制台的对象更新上。

【讨论】:

    【解决方案3】:

    聊天后了解了数据的形状,在 Code Review 的帮助下,我们可以这样做:

    const json = [{
      return_string: {
        "barcode": ["5000159459228", "5000159459229", "5000159459230"],
        "scan_date": ["20180825173416", "20180825173416", "20180825173416"],
        "name": ["Twix Twin Chocolate Bars - 50g - Pack of 6 (50g x 6 Bars) (1.76 oz  x  6)", "Twix Twin Chocolate Bars - 50g - Pack of 6 (50g x 6 Bars) (1.76 oz  x  6)", "Twix Twin Chocolate Bars - 50g - Pack of 6 (50g x 6 Bars) (1.76 oz  x  6)"],
        "description": ["Twix Twin Chocolate Bars - 50g - Pack of 6 (50g x 6 Bars) (1.76 oz  x  6)", "Twix Twin Chocolate Bars - 50g - Pack of 6 (50g x 6 Bars) (1.76 oz  x  6)", "Twix Twin Chocolate Bars - 50g - Pack of 6 (50g x 6 Bars) (1.76 oz  x  6)"],
        "image": ["http://thumbs2.ebaystatic.com/m/mv0sDuMCXy5TgjQFYC0CJAQ/140.jpg", "http://thumbs2.ebaystatic.com/m/mv0sDuMCXy5TgjQFYC0CJAQ/140.jpg", "http://thumbs2.ebaystatic.com/m/mv0sDuMCXy5TgjQFYC0CJAQ/140.jpg"],
        "price": ["1", "2", "3"]
      }
    }];
    
    const fakeRequest = () => new Promise( resolve =>
      setTimeout( () => resolve( json ) )
    );
    
    class App extends React.Component {
      state = {
        data: "",
      }
    
      componentDidMount() {
        fakeRequest()
          .then( res => {
            this.setState({
              data: res[0].return_string,
            })
          })
      }
    
      renderData = () => {
        const { data } = this.state;
        const values = Object.values(data);
        const keys = Object.keys(data);
        
        const transposed = values[0].map((col, i) =>
          values.map(row => row[i]));
        
        const items = transposed.map(itemArr =>
          keys.reduce((acc, key, i) => (
            { ...acc, [key]: itemArr[i] }), {})
        );
        
        return items.map( item => (
          <div style={{ border: "1px solid black", marginBottom: "3px" }}>
            <p>Barcode: {item.barcode}</p>
            <p>Scan date: {item.scan_date}</p>
            <p>Name: {item.name}</p>
            <p>Description: {item.description}</p>
            <p>Image: {item.image}</p>
            <p>Price: {item.price}</p>
          </div>
        ) )
      }
    
      render() {
        return <div>{this.state.data && this.renderData()}</div>;
      }
    }
    
    ReactDOM.render(<App />, document.getElementById("root"));
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react.min.js"></script>
    <script src="https://cdnjs.cloudflare.com/ajax/libs/react/15.1.0/react-dom.min.js"></script>
    <div id="root"></div>

    困难的部分是将数据正确地转换为对象数组。因为,这种数据形状对我来说有点奇怪:) 一个包含数组属性的对象。这些数组元素按顺序匹配。呼:)

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2020-06-04
      • 1970-01-01
      • 1970-01-01
      • 2020-10-09
      • 2017-08-30
      • 2020-09-02
      • 2020-09-08
      • 1970-01-01
      相关资源
      最近更新 更多