【问题标题】:React Cannot read property 'map' of undefined反应无法读取未定义的属性“地图”
【发布时间】:2018-12-18 12:51:46
【问题描述】:

在反应中,我可以在组件中设置一个变量,但我很难在常规 JavaScript 文件 - list.js 中设置 var data = {}

我使用 Axios 检索我的数据,但 data.map 未定义,但数据未定义,如控制台所示。我假设这是因为在从 Axios.get 检索数据之前调用了 data.map。之所以这么说,是因为我在做一个console.log(data)的时候,可以看到console里面的数据:

import React from 'react';
import Axios from 'axios';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Paper from '@material-ui/core/Paper';

var data = {};

function componentDidMount() {
    Axios.get('http://localhost/api/get-coins/')
        .then(
            responseJson => {
                data = JSON.parse(JSON.stringify(responseJson.data));
                // console.log(data);
                return data;
            }
        )
        .catch(
            error => console.log(error)
        )
}

function SimpleTable(props) {
    const { classes } = props;
    data = componentDidMount();
    console.log(data);
    return (
        <Paper className={classes.root}>
            <Table className={classes.table}>
                <TableHead>
                    <TableRow>
                        <TableCell numeric>ID</TableCell>
                        <TableCell>Name</TableCell>
                        <TableCell numeric>Price</TableCell>
                    </TableRow>
                </TableHead>
                <TableBody>
                    {data.map(n => {
                        return (
                            <TableRow key={n.id}>
                                <TableCell component="th" scope="row">
                                    {n.name}
                                </TableCell>
                                <TableCell numeric>{n.price}</TableCell>
                            </TableRow>
                        );
                    })}
                </TableBody>
            </Table>
        </Paper>
    );
}

SimpleTable.propTypes = {
    classes: PropTypes.object.isRequired,
};

如何先检索数据,然后调用 SimpleTable 原型?

我用 setTimeout 尝试了以下操作,但收到返回 null 的错误,但我再次在控制台中看到数据:

function SimpleTable(props) {
    var data = {};

    const { classes } = props;
    data = Axios.get('http://local.sites/ng6crud/api/get-coins/')
        .then(
            responseJson => {
                data = JSON.parse(JSON.stringify(responseJson.data));
                console.log(data);
                setTimeout(function () {
                    return (
                        <Paper className={classes.root}>
                            <Table className={classes.table}>
                                <TableHead>
                                    <TableRow>
                                        <TableCell numeric>ID</TableCell>
                                        <TableCell>Name</TableCell>
                                        <TableCell numeric>Price</TableCell>
                                    </TableRow>
                                </TableHead>
                                <TableBody>
                                    {data.map(n => {
                                        return (
                                            <TableRow key={n.id}>
                                                <TableCell component="th" scope="row">
                                                    {n.name}
                                                </TableCell>
                                                <TableCell numeric>{n.price}</TableCell>
                                            </TableRow>
                                        );
                                    })}
                                </TableBody>
                            </Table>
                        </Paper>
                    );
                }, 1000);
            }
        )
        .catch(
            error => console.log(error)
        );
}

我觉得使用 React,我在每一步都在战斗。请帮助并提前感谢

编辑: 感谢@guillaume 的回答。我能够让它工作。我想指出我试图在不创建类或组件的情况下执行此操作,但我想在渲染发生之前无法及时获取数据。

import React from 'react';
import Axios from 'axios';
import PropTypes from 'prop-types';
import { withStyles } from '@material-ui/core/styles';
import Table from '@material-ui/core/Table';
import TableBody from '@material-ui/core/TableBody';
import TableCell from '@material-ui/core/TableCell';
import TableHead from '@material-ui/core/TableHead';
import TableRow from '@material-ui/core/TableRow';
import Paper from '@material-ui/core/Paper';

class List extends React.Component {
    constructor(props) {
        super(props);
        this.state = {data: []}
    }

    componentDidMount() {
        Axios.get('http://localhost/api/get-coins/')
            .then(
                responseJson => {
                    this.setState({
                        data: JSON.parse(JSON.stringify(responseJson.data))
                    });
                    return this.state.data;
                }
            )
            .catch(
                error => console.log(error)
            )
    }

    render() {
        return (
            <Paper>
                <Table>
                    <TableHead>
                        <TableRow>
                            <TableCell numeric>ID</TableCell>
                            <TableCell>Name</TableCell>
                            <TableCell numeric>Price</TableCell>
                        </TableRow>
                    </TableHead>
                    <TableBody>
                        {this.state.data.map(n => {
                            return (
                                <TableRow key={n.id}>
                                    <TableCell component="th" scope="row">
                                        {n.id}
                                    </TableCell>
                                    <TableCell component="th" scope="row">
                                        {n.name}
                                    </TableCell>
                                    <TableCell numeric>{n.price}</TableCell>
                                </TableRow>
                            );
                        })}
                    </TableBody>
                </Table>
            </Paper>
        );
    }
}

export default List

【问题讨论】:

  • 使用类而不是功能组件,并在该类中定义 componentDidMount 方法。你现在这样做的方式实际上并没有调用 React 生命周期方法 componentDidMount
  • 你不应该自己打电话给componentDidMount。在你的网络请求的回调中使用this.setState,并在你的渲染方法中使用它。
  • 你的组件结构很混乱。为什么你不遵循文档的模式?这将使您的问题的解决方案变得更加容易
  • @MatheusReis,我正在使用来自他们网站链接的代码 - codesandbox.io/s/pp2q98445x - 唯一的区别是我使用 Axios.get() 检索我的数据
  • @Guillaume - 我试图避免使用类或组件,因为我正在关注 material-ui 网站上链接中的示例 - 请参阅之前的评论

标签: javascript reactjs


【解决方案1】:

map 是数组的一种方法,但您将数据初始化为对象。执行var data = [];,您的组件将成功调用空数组上的.map 并呈现一个空表。数据准备好后重新渲染您的组件,然后表格将被填充。

【讨论】:

  • 那并没有解决他的问题,因为在Axios.get().then()里面,数据是一个数组
【解决方案2】:

你不能在函数式组件中使用 React 生命周期方法,除非你使用 react-pure-lifecycle

目前,您的函数 componentDidMount 就是:您自己定义的函数。它的行为与 React 的 componentDidMount 方法不同。

你需要使用一个类组件来使用这个方法:

class SimpleTable extends React.Component {
    constructor(props) {
        super(props);
        this.state = {data: []}
    }

    componentDidMount() {
        Axios.get('http://localhost/api/get-coins/')
            .then(
                responseJson => {
                    this.setState({
                        data: JSON.parse(JSON.stringify(responseJson.data));

                    });

                    return data;
                }
            )
            .catch(
                error => console.log(error)
            )
    }

    render() {
        const { classes } = props;
        return (
            <Paper className={classes.root}>
                <Table className={classes.table}>
                    <TableHead>
                        <TableRow>
                            <TableCell numeric>ID</TableCell>
                            <TableCell>Name</TableCell>
                            <TableCell numeric>Price</TableCell>
                        </TableRow>
                    </TableHead>
                    <TableBody>
                        {data.map(n => {
                            return (
                                <TableRow key={n.id}>
                                    <TableCell component="th" scope="row">
                                        {n.name}
                                    </TableCell>
                                    <TableCell numeric>{n.price}</TableCell>
                                </TableRow>
                            );
                        })}
                    </TableBody>
                </Table>
            </Paper>
        );
    }
}

【讨论】:

  • 谢谢@guillaume。我收到了与您的代码有关的一些不同问题,但您的回答帮助我完成了最终版本,我将发布并感谢您对我的帮助。顺便说一句,即使我使用 someFunc 作为使用 Axios 的函数的名称,它仍然没有以正确的方式返回数据
猜你喜欢
  • 2022-01-25
  • 1970-01-01
  • 2021-12-02
  • 2020-09-23
  • 2019-04-26
  • 1970-01-01
  • 1970-01-01
  • 2021-08-28
  • 2021-02-01
相关资源
最近更新 更多