无法读取未定义地图的属性

时间:2021-01-06 20:09:18

标签: reactjs

在通过服务器的 GET http 请求获取后,我试图在我的本地主机浏览器上显示一个 json 数据集。

代码:

imports ...
      
  class See extends Component {
      state = { 
         Sessions :[] , 
       }
       

       async componentDidMount(){
           
        const {data: Sessions}= await axios.get("http://localhost:8765/...");
        
        this.setState({Sessions});
    
       }
      render() { 
        
          return ( 
            <React.Fragment>
              <Table striped bordered hover>
                 <thead>
                   <tr> 
                     <th>PointID</th>
                     <th>PointSessions</th>
                     <th>EnergyDelivered</th>
                   </tr>
                 </thead>
                <tbody>
                {this.state.Sessions.SessionsSummaryList.map(Session => (
                   <tr key="Session.PointID">
                   <th>Session.PointID</th>

                   </tr>  
                   ))}
             </tbody>
          </Table>
        </React.Fragment>                            
          );  }
  }
   
  export default See;

这个数据集包含一些数据字段以及一个json对象列表(每个包含3个字段,如表头所示)。

在 chrome 开发工具中使用 React 扩展,我可以看到数据集以状态加载并且看起来像它应该的那样,但是我收到了这个错误:

TypeError: Cannot read property 'map' of undefined

我还通过一个简单的打印看到的是,在这段代码的运行过程中,render 方法被调用了 2 次。是不是第一次运行时没有初始化 Sessions 值?

如果是,我该如何解决这个问题?

3 个答案:

答案 0 :(得分:1)

您可以先检查数组是否退出,然后进行解构,然后执行以下操作:

#pragma once
// GLEW
#include <GL/glew.h>

// Other Libs
#include "stb_image.h"

// Other includes
#include "Model.h"
#include <vector>


class TextureLoading
{
public:
    static GLuint LoadTexture(GLchar *path)
    {
        unsigned int textureID;
        glGenTextures(1, &textureID);

        int width, height, nrComponents;
        unsigned char *data = stbi_load(path, &width, &height, &nrComponents, 0);
        if (data)
        {
            GLenum format;
            if (nrComponents == 1)
                format = GL_RED;
            else if (nrComponents == 3)
                format = GL_RGB;
            else if (nrComponents == 4)
                format = GL_RGBA;

            glBindTexture(GL_TEXTURE_2D, textureID);
            glTexImage2D(GL_TEXTURE_2D, 0, format, width, height, 0, format, GL_UNSIGNED_BYTE, data);
            glGenerateMipmap(GL_TEXTURE_2D);

            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
            glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);

            stbi_image_free(data);

        }
        else
        {
            std::cout << "Failed to load texture" << path << std::endl;
            stbi_image_free(data);
        }

        return textureID;
    }


    static GLuint LoadCubemap(vector<const GLchar * > faces)
    {
        GLuint textureID;
        glGenTextures(1, &textureID);

        int width, height, nrChannels;
        for (unsigned int i = 0; i < faces.size(); i++)
        {
            unsigned char *data = stbi_load(faces[i], &width, &height, &nrChannels, 0);
            if (data)
            {
                glTexImage2D(GL_TEXTURE_CUBE_MAP_POSITIVE_X + i, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, data);
                stbi_image_free(data);
            }
            else
            {
                std::cout << "Cubemap texture failed to load at path: " << faces[i] << std::endl;
                stbi_image_free(data);
            }
        }
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
        glTexParameteri(GL_TEXTURE_CUBE_MAP, GL_TEXTURE_WRAP_R, GL_CLAMP_TO_EDGE);
        glBindTexture(GL_TEXTURE_CUBE_MAP, 0);

        return textureID;
    }

};

答案 1 :(得分:1)

您的问题是 react 正在尝试映射您的对象,但该对象尚未填充数据。

我已经很长时间没有使用基于类的组件了,所以我只是告诉你如何使用它。

创建一个布尔状态(我用基于函数的组件编写,只需转换它)

const [isFilled, setIsFilled] = useState(false);

现在就说

<块引用>

isFilled == true

这样做:

{this.state.Sessions.SessionsSummaryList.map(Session => (
      <tr key="Session.PointID">
      <th>Session.PointID</th>

       </tr>  
   ))}

每当您使用 axios 获取数据时,您都必须:

axios.get(`XAXAXAXAXAXAXAX`)
      .then(res => {
        setIsFilled(true);
      })

答案 2 :(得分:1)

正如在其他答案中所说,您需要检查您的状态是否具有您正在使用的值。在类组件中,状态不会立即更新,因此您需要一个条件来验证它。这是 repro on Stackblitz 和代码:

import React from "react";
import { render } from "react-dom";
import axios from "axios";
import "./style.css";

class App extends React.Component {
  state = {
    user: null
  };

  async componentDidMount() {
    const { data: user } = await axios.get(
      "https://jsonplaceholder.typicode.com/todos/1"
    );

    console.log("user = ", user);

    this.setState({ user });
  }

  render() {
    // Here is the conditions needed to prevent errors when state isn't refreshed yet
    if (!this.state.user) return null;
    return <div>Test = {this.state.user.userId}</div>;
  }
}

render(<App />, document.getElementById("root"));