Javascript 未处理的拒绝(TypeError):ships.reduce不是一个函数
我使用特定的API构建了一个船可视化工具。API返回一个json响应,我将其注入表中 问题:有时在白天,我注意到应用程序会停止工作,抛出以下实例:Javascript 未处理的拒绝(TypeError):ships.reduce不是一个函数,javascript,node.js,reactjs,Javascript,Node.js,Reactjs,我使用特定的API构建了一个船可视化工具。API返回一个json响应,我将其注入表中 问题:有时在白天,我注意到应用程序会停止工作,抛出以下实例: 未处理的拒绝(TypeError):ships.reduce不是一个函数 以下是错误的打印屏幕的完整性: 下面是我正在使用的代码: const ShipTracker = ({ ships, setActiveShip }) => { console.log("These are the ships: ", { ships });
未处理的拒绝(TypeError):ships.reduce不是一个函数
以下是错误的打印屏幕的完整性:
下面是我正在使用的代码:
const ShipTracker = ({ ships, setActiveShip }) => {
console.log("These are the ships: ", { ships });
return (
<div className="ship-tracker">
<Table className="flags-table" responsive hover>
<thead>
<tr>
<th>#</th>
<th>MMSI</th>
<th>TIMESTAMP</th>
<th>LATITUDE</th>
<th>LONGITUDE</th>
<th>COURSE</th>
<th>SPEED</th>
<th>HEADING</th>
<th>NAVSTAT</th>
<th>IMO</th>
<th>NAME</th>
<th>CALLSIGN</th>
</tr>
</thead>
<tbody>
{ships.map((ship, index) => {
// <-- Error Here
const {
MMSI,
TIMESTAMP,
LATITUDE,
LONGITUDE,
COURSE,
SPEED,
HEADING,
NAVSTAT,
IMO,
NAME,
CALLSIGN
} = ship.AIS;
const cells = [
MMSI,
TIMESTAMP,
LATITUDE,
LONGITUDE,
COURSE,
SPEED,
HEADING,
NAVSTAT,
IMO,
NAME,
CALLSIGN
];
return (
<tr
onClick={() =>
setActiveShip(
ship.AIS.NAME,
ship.AIS.LATITUDE,
ship.AIS.LONGITUDE
)
}
key={index}
>
<th scope="row">{index}</th>
{cells.map(cell => (
<td key={ship.AIS.MMSI}>{cell}</td>
))}
</tr>
);
})}
</tbody>
</Table>
</div>
);
};
const ShipTracker=({ships,setActiveShip})=>{
log(“这些是船:”,{ships});
返回(
#
MMSI
时间戳
纬度
经度
课程
速度
标题
导航器
依我所见
名称
呼号
{ships.map((ship,index)=>{
//
{index}
{cells.map(cell=>(
{cell}
))}
);
})}
);
};
Googlemap.js
class BoatMap extends Component {
constructor(props) {
super(props);
this.state = {
ships: [],
filteredShips: [],
type: "All",
shipTypes: [],
activeShipTypes: []
};
this.updateRequest = this.updateRequest.bind(this);
this.countDownInterval = null;
this.updateInterval = null;
this.map = null;
this.maps = null;
this.previousTimeStamp = null;
}
async updateRequest() {
const url = "http://localhost:3001/hello";
const fetchingData = await fetch(url);
const ships = await fetchingData.json();
console.log("fetched ships", ships);
if (JSON.stringify(ships) !== "{}") {
if (this.previousTimeStamp === null) {
this.previousTimeStamp = ships.reduce(function(obj, ship) {
obj[ship.AIS.NAME] = ship.AIS.TIMESTAMP;
return obj;
}, {});
}
this.setState({
ships: ships,
filteredShips: ships
});
this.props.callbackFromParent(ships);
for (let ship of ships) {
if (this.previousTimeStamp !== null) {
if (this.previousTimeStamp[ship.AIS.NAME] === ship.AIS.TIMESTAMP) {
this.previousTimeStamp[ship.AIS.NAME] = ship.AIS.TIMESTAMP;
console.log("Same timestamp: ", ship.AIS.NAME, ship.AIS.TIMESTAMP);
continue;
} else {
this.previousTimeStamp[ship.AIS.NAME] = ship.AIS.TIMESTAMP;
}
}
let _ship = {
// ship data ...
};
const requestOptions = {
method: "POST",
headers: { "Content-Type": "application/json" },
body: JSON.stringify(_ship)
};
await fetch(
"http://localhost:3001/users/vessles/map/latlng",
requestOptions
);
// console.log('Post', Date());
}
}
}
render() {
const noHoverOnShip = this.state.hoverOnActiveShip === null;
return (
<div className="google-map">
<GoogleMapReact
bootstrapURLKeys={{ key: "key" }}
center={{
lat: this.props.activeShip ? this.props.activeShip.latitude : 37.99,
lng: this.props.activeShip
? this.props.activeShip.longitude
: -97.31
}}
zoom={5.5}
onGoogleApiLoaded={({ map, maps }) => {
this.map = map;
this.maps = maps;
// we need this setState to force the first mapcontrol render
this.setState({ mapControlShouldRender: true, mapLoaded: true });
}}
>
{this.state.mapLoaded && (
<div>
<Polyline
map={this.map}
maps={this.maps}
markers={this.state.trajectoryData}
lineColor={this.state.trajectoryColor}
/>
</div>
)}
{Array.isArray(this.state.filteredShips) ? (
this.state.filteredShips.map(ship => (
<Ship
ship={ship}
key={ship.AIS.MMSI}
lat={ship.AIS.LATITUDE}
lng={ship.AIS.LONGITUDE}
logoMap={this.state.logoMap}
logoClick={this.handleMarkerClick}
logoHoverOn={this.handleMarkerHoverOnShip}
logoHoverOff={this.handleMarkerHoverOffInfoWin}
/>
))
) : (
<div />
)}
</GoogleMapReact>
</div>
);
}
}
export default class GoogleMap extends React.Component {
state = {
ships: [],
activeShipTypes: [],
activeCompanies: [],
activeShip: null,
shipFromDatabase: []
};
setActiveShip = (name, latitude, longitude) => {
this.setState({
activeShip: {
name,
latitude,
longitude
}
});
};
setShipDatabase = ships => {
this.setState({ shipFromDatabase: ships });
};
// passing data from children to parent
callbackFromParent = ships => {
this.setState({ ships });
};
render() {
return (
<MapContainer>
{/* This is the Google Map Tracking Page */}
<pre>{JSON.stringify(this.state.activeShip, null, 2)}</pre>
<BoatMap
setActiveShip={this.setActiveShip}
activeShip={this.state.activeShip}
handleDropdownChange={this.handleDropdownChange}
callbackFromParent={this.callbackFromParent}
shipFromDatabase={this.state.shipFromDatabase}
renderMyDropDown={this.state.renderMyDropDown}
// activeWindow={this.setActiveWindow}
/>
<ShipTracker
ships={this.state.ships}
setActiveShip={this.setActiveShip}
onMarkerClick={this.handleMarkerClick}
/>
</MapContainer>
);
}
}
class BoatMap扩展组件{
建造师(道具){
超级(道具);
此.state={
船舶:[],
过滤设备:[],
键入:“全部”,
船型:[],
activeShipTypes:[]
};
this.updateRequest=this.updateRequest.bind(this);
this.countDownInterval=null;
this.updateInterval=null;
this.map=null;
this.maps=null;
this.previousTimeStamp=null;
}
异步更新请求(){
常量url=”http://localhost:3001/hello";
const fetchingData=等待获取(url);
const ships=await fetchingData.json();
控制台日志(“获取的船舶”,船舶);
if(JSON.stringify(ships)!=“{}”){
if(this.previousTimeStamp==null){
this.previousTimeStamp=ships.reduce(函数(obj,ship){
obj[ship.AIS.NAME]=ship.AIS.TIMESTAMP;
返回obj;
}, {});
}
这是我的国家({
船舶:船舶,
过滤船
});
this.props.callbackFromParent(ships);
为了(让一艘船一艘船){
if(this.previousTimeStamp!==null){
if(this.previousTimeStamp[ship.AIS.NAME]==ship.AIS.TIMESTAMP){
this.previousTimeStamp[ship.AIS.NAME]=ship.AIS.TIMESTAMP;
log(“相同的时间戳:”,ship.AIS.NAME,ship.AIS.timestamp);
继续;
}否则{
this.previousTimeStamp[ship.AIS.NAME]=ship.AIS.TIMESTAMP;
}
}
让我们装运={
//船舶数据。。。
};
常量请求选项={
方法:“张贴”,
标题:{“内容类型”:“应用程序/json”},
正文:JSON.stringify(_ship)
};
待命(
"http://localhost:3001/users/vessles/map/latlng",
请求选项
);
//log('Post',Date());
}
}
}
render(){
const noHoverOnShip=this.state.hoverOnActiveShip==null;
返回(
{
this.map=map;
this.maps=maps;
//我们需要此设置状态来强制第一次mapcontrol渲染
this.setState({mapControlShouldRender:true,mapLoaded:true});
}}
>
{this.state.mapload&&(
)}
{Array.isArray(this.state.filteredShips)(
this.state.filteredShips.map(ship=>(
))
) : (
)}
);
}
}
导出默认类GoogleMap扩展React.Component{
状态={
船舶:[],
activeShipTypes:[],
活动公司:[],
activeShip:null,
shipFromDatabase:[]
};
setActiveShip=(名称、纬度、经度)=>{
这是我的国家({
活动船舶:{
名称
纬度,
经度
}
});
};
setShipDatabase=ships=>{
this.setState({shipFromDatabase:ships});
};
//将数据从子级传递到父级
callbackFromParent=发货=>{
这个.setState({ships});
};
render(){
返回(
{/*这是谷歌地图跟踪页面*/}
{
ships?.map((ship, index) =>
...
// or
ships && ships.length > 0 && ships.map((ship, index) =>
....
}
{JSON.stringify(this.state.activeShip,null,2)}
);
}
}
到目前为止我所做的:
1) 我也来帮我解决这个问题,但运气不好
2) 我也咨询了他们,但他们都没有帮助我找出问题所在
3) 我深入研究了这个问题,发现了很多问题
4) 我读书。然而,这两种方法都没有帮助我解决这个问题
5) 我也发现非常有用,但仍然没有解决方案
Thanls为解决这个问题指明了正确的方向。这可能是因为
在调用reduce时,ships
不是数组,可能是null
如果传递的父组件上的ships是state,那么它最初可能为null,然后获得更新,那么第一次呈现组件时,它的调用reduce是否为null
如果您使用的JavaScript版本支持空传播,则可以使用
ships?.reduce
以便在第一次呈现时,如果它为null,它不会尝试调用null上的reduce函数,但是当它呈现时,一切都应该很好,这是一种非常常见的模式
如果您的JavaScript版本不支持空传播,则可以使用
ships&&ships.length>0&&ships.reduce(…
所以你也应该改变
{ships.map((ship,index)=>{/这无法解决为什么ships
道具不总是数组的问题,但它将帮助您保护代码免受此未处理异常的影响
{Array.isArray(ships)和&ships.map((ship,index)=>{
常数
<tbody>
{Array.isArray(ships) && ships.map((ship, index) => {
const {
MMSI,
// rest of your code here