React:Nodejs API响应后未显示的元素

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

我有一个Node API,它以JSON格式返回数据并将其发送到React Component App,它将其存储在其状态(nearbyShops)中,然后将其传递给NearbyShop组件道具。事情是,即使我使用componentDidMount,我也没有显示内容。

App.js

import React, { Component } from 'react';
import axios from 'axios';
import './App.css';
import NearbyShop from './NearbyShop';

class App extends Component {

    constructor(props) {
        super(props);
        this.state = {
            lat: 0,
            long: 0,
            nearbyShops: []
        }
    }

    componentDidMount() {
        var that = this;
        // Get the user's location (lat & long) in the state object
        const url = 'https://freegeoip.net/json/';
        axios.get(url)
            .then((response) => response.data)
            // Get the long & lat of the end-user
            .then((data) => that.setState({
                                lat: data.latitude,
                                long: data.longitude
            }))
            // Call our built-in Nearby API with the lat & long of the end-user
            .then(function (data) {
                axios.get('/nearby', {
                    params: {
                        lat: that.state.lat,
                        long: that.state.long
                    }
                })
                .then((response) => that.setState({
                    nearbyShops: response.data.nearbyShops
                }))
                .catch(function (error) {
                    console.log(error);
                });
            })            
            .catch(function (error) {
                console.log(error);
            });
    }

  render() {
    return (
      <div className="App">
            <h1>Shops List</h1>
            <NearbyShop shopsList={this.state.nearbyShops} />
      </div>
    );
  }
}

export default App;

NearbyShop.js

import React, { Component } from 'react';
import ReactDOM from 'react-dom';
import {
    Card, Button, CardImg, CardTitle, CardText, CardGroup,
    CardSubtitle, CardBody
} from 'reactstrap';


class NearbyShop extends React.Component {
    constructor(props) {
        super(props);
        this.state = {
            shopsList: props.shopsList
        }
    }

    componentDidMount() {
        const shopsList = this.props.shopsList;
        this.setState({
            shopsList: shopsList
        });
    }

    render() { 

        if (this.state.shopsList.length == 0)
            return null;

        let shops = this.state.shopsList && this.state.shopsList.map(function (shop, i) {
            <Card key={i}>
                <CardImg top width="100%" src={shop.picture} alt="Card image cap" />
                <CardBody>
                    <CardTitle>{shop.name}</CardTitle>
                    <CardSubtitle>Card subtitle</CardSubtitle>
                    <CardText>{shop.email}</CardText>
                    <Button>Fall in love</Button>
                </CardBody>
            </Card>
        })

        return (
            <CardGroup>
                {shops}
            </CardGroup>
    );
    }
}

export default NearbyShop;
javascript node.js reactjs
2个回答
1
投票

NearbyShop组件是混合状态和道具。

NearbyShop不需要管理state,因为数据是通过props从父组件传递的。当父提供的props从API请求更改时,它将重新呈现。

当前代码集是组件初始化时的state,它永远不会更新,因为组件未初始化或mounted再次,仅渲染。所以只有初始状态,空数组[]才会被渲染。

class NearbyShop extends React.Component {
    render() {
        const { shopsList } = this.props
        if (!shopsList || shopsList.length == 0)
            return null;

        const shops = shopsList.map(function (shop, i) {
            <Card key={i}>
                <CardImg top width="100%" src={shop.picture} alt="Card image cap" />
                <CardBody>
                    <CardTitle>{shop.name}</CardTitle>
                    <CardSubtitle>Card subtitle</CardSubtitle>
                    <CardText>{shop.email}</CardText>
                    <Button>Fall in love</Button>
                </CardBody>
            </Card>
        })

        return (
            <CardGroup>
                {shops}
            </CardGroup>
        );
    }
}

另外,正如Kryten所说,App API请求混合了promises和setState回调。这可能会导致您的API请求与您的状态更新失去同步,并最终导致呈现的结果不一致。状态更改可以在最后一起批处理以进行单个更新/呈现。

componentDidMount() {
    // Get the user's location (lat & long) in the state object
    const url = 'https://freegeoip.net/json/';
    const state_updates = {}
    axios.get(url)
        .then((response) => {
            const data = response.data
            // Get the long & lat of the end-user
            state_updates.lat = data.latitude
            state_updates.long = data.longitude
            return axios.get('/nearby', {
                params: {
                    lat: state_updates.lat,
                    long: state_updates.long
                }
            })
        })
        .then((response) => {
            state_updates.nearbyShops = response.data.nearbyShops
            this.setState(state_updates)
            return true
        })
        .catch(function (error) {
            console.log(error);
        })
}

这段代码仍然没有等待setState完成,但现在它是最后一项工作,而承诺流程不依赖于组件state中的异步更改。


-1
投票

问题可能源于setState不返回承诺的事实 - 如果您希望在更新后使用更新状态值,则需要回调。

因此,当您尝试到达附近的位置时,您可能会失败:

axios.get(url)
        .then((response) => response.data)
        // Get the long & lat of the end-user
        .then((data) => that.setState({
                            lat: data.latitude,
                            long: data.longitude
        }))
        // Call our built-in Nearby API with the lat & long of the end-user
        .then(function (data) {

            // data is undefined here, since it was returned from
            // setState. In addition, there is no guarantee that
            // the state has been updated and your lat & long values
            // are probably not accurate

            axios.get('/nearby', {
                params: {
                    lat: that.state.lat,
                    long: that.state.long
                }
            })

        })

documentation for setState说:

将setState()视为请求而不是更新组件的立即命令。为了获得更好的感知性能,React可能会延迟它,然后在一次通过中更新几个组件。 React不保证立即应用状态更改。

© www.soinside.com 2019 - 2024. All rights reserved.