我有一个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;
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
中的异步更改。
问题可能源于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
}
})
})
将setState()视为请求而不是更新组件的立即命令。为了获得更好的感知性能,React可能会延迟它,然后在一次通过中更新几个组件。 React不保证立即应用状态更改。