特定のAPIを使用してボートビジュアライザーを作成しました。APIは、テーブルに挿入したjson応答を返します。
問題:日中に、アプリケーションが次のインスタンスをスローして動作を停止することに気付いたことがあります。
Unhandled Rejection (TypeError): ships.reduce is not a function
エラーの印刷画面を完全にするために、以下を参照してください。
私が使用しているコードの下:
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>
);
};
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>
);
}
}
私がこれまでにしたこと:
1)私も問題を解決するのを助けるためにこの情報源に出くわしましたが、運がありませんでした。
2)また、私はこの他の情報源とこれも調べましたが、どちらも問題が何であるかを理解するのに役立ちませんでした。
3)私は問題をさらに掘り下げて、このソースも見つけました。
4)私もこれを読みました。しかし、これらのどちらも私が問題を解決するのに役立ちませんでした。
5)このソースも非常に便利でしたが、まだ解決策がありません。
この問題を解決するための正しい方向を指し示してくれてありがとう。
これを回避する1つの方法は、fetch
内部のリクエストで問題が発生した場合に、デフォルトで空の配列に設定することですupdateRequest
。
async updateRequest() {
const url = "http://localhost:3001/hello";
const defaultValue = [];
const ships = await fetchShips(url, defaultValue);
// safe to use `Array` methods on an empty `array`
if (this.previousTimeStamp === null) {
this.previousTimestamp = ships.reduce(...);
}
}
function fetchShips(url, defaultValue) {
return fetch(url)
.then(response => {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(data => {
if (Array.isArray(data)) {
return data;
}
// return the default value (empty array)
// so that your application doesn't crash
return defaultValue;
})
.catch(error => {
console.error(error.message);
// catch other errors and return the default
// value (empty array), so that your application doesn't crash
return defaultValue;
});
}
ただし、エラーを適切に処理し、何も表示しないのではなく、ユーザーエクスペリエンスを向上させるために問題が発生したことを示すメッセージを表示する必要があります。
async updateRequest() {
const url = "http://localhost:3001/hello";
const defaultValue = [];
const ships = await fetchShips(url, defaultValue).catch(e => e);
if (ships instanceof Error) {
// handle errors appropriately
return;
}
// otherwise continue, with an empty array still a
// possibility, but won't break the app
if (this.previousTimeStamp === null) {
this.previousTimestamp = ships.reduce(...);
}
}
function fetchShips(url, defaultValue) {
return fetch(url)
.then(response => {
if (!response.ok) {
throw Error(response.statusText);
}
return response.json();
})
.then(data => {
if (Array.isArray(data)) {
return data;
}
// return the default value (empty array)
// so that your application doesn't crash
return defaultValue;
});
}
これは、ships
propが常に配列であるとは限らない理由を解決しませんが、この未処理の例外からコードを保護するのに役立ちます
<tbody>
{Array.isArray(ships) && ships.map((ship, index) => {
const {
MMSI,
// rest of your code here
これはおそらくships
、reduceが呼び出された時点で配列ではないために発生しています。おそらく、そのnullですか?
船が渡される親コンポーネントの状態である場合、おそらく最初はnullであり、その後更新を取得します。したがって、コンポーネントが最初にレンダリングされるときに、呼び出しはnullでreduce?
使用しているJavaScriptのバージョンがnull伝播をサポートしている場合は、
ships?.reduce
そのため、最初にレンダリングされたときにnullの場合、nullでreduce関数を呼び出そうとはしませんが、レンダリングされたときはすべて問題ないはずです。これは非常に一般的なパターンです。
JavaScriptバージョンがnull伝播をサポートしていない場合は、次を使用できます
ships && ships.length > 0 && ships.reduce(...
だからあなたも変更する必要があります
{ships.map((ship, index) => { // <-- Error Here
に
{
ships?.map((ship, index) =>
...
// or
ships && ships.length > 0 && ships.map((ship, index) =>
....
}
Reba McEntire が息子の Shelby Blackstock と共有しているクリスマスの伝統について学びましょう。
メーガン・マークルとマライア・キャリーが自然な髪の上でどのように結合したかについて、メーガンの「アーキタイプ」ポッドキャストのエピソードで学びましょう.
ハリー王子が家族、特にチャールズ王とウィリアム王子との関係について望んでいると主張したある情報源を発見してください。
ワイノナ・ジャッドが、母親のナオミ・ジャッドが亡くなってから初めての感謝祭のお祝いを主催しているときに、彼女が今では家長であることをどのように認識したかを学びましょう.
Air travel is far more than getting from point A to point B safely. How much do you know about the million little details that go into flying on airplanes?
The world is a huge place, yet some GeoGuessr players know locations in mere seconds. Are you one of GeoGuessr's gifted elite? Take our quiz to find out!
ランボルギーニの創設者であるフェルッチオランボルギーニが100歳になるのは毎日ではありません(そうです、彼は死んでいて、まだ死んでいると思います。
Appleが自動車分野に参入するという噂はかなり前から渦巻いており、AppleウォッチャーがSixtyEight Researchという会社がAppleの自動車研究開発のシェル会社である可能性が高いと判断したとき、その渦巻きは本当に渦巻いた。また、会社が購入した車は1台だけであることが知られており、その車はAppleが何を考えているかについての手がかりでいっぱいになる可能性があることも伝えています。
太陽系の外側にある架空の大きな物体である惑星Xの探索は、何十年にもわたって人間を魅了してきました。その検索の最新の章は、地球の10倍の大きさで、公転周期が15であるほど遠くにある惑星を指しています。
カムニュートンは昨日、簡単な265ヤードと3回のタッチダウンでファルコンズを引き裂き、別の素晴らしいゲームをしました。その日のハイライトは、上のタッチダウンスローでした。これは、視聴するたびにばかげているだけです。
ロシアのフィギュアスケーター、カミラ・バリエバが関与したドーピング事件が整理されているため、チームは2022年北京冬季オリンピックで獲得したメダルを待っています。
何千人ものAmazonの買い物客がMulberry Silk Pillowcaseを推奨しており、現在販売中. シルクの枕カバーにはいくつかの色があり、髪を柔らかく肌を透明に保ちます。Amazonで最大46%オフになっている間にシルクの枕カバーを購入してください
ラファイエット警察署は、「不審な男性が女性に近づいた」という複数の苦情を受けて、12 月にパデュー大学の教授の捜査を開始しました。
私たちの周りの世界と同じように、言語は常に変化しています。以前の時代では、言語の変化は数年または数十年にわたって発生していましたが、現在では数日または数時間で変化する可能性があります。
認知症を患っている 91 歳のアジア人女性が最近、47 番街のアウター サンセット地区でロメオ ロレンゾ パーハムに襲われました。伝えられるところによると、被害者はサンフランシスコの通りを歩いていたところ、容疑者に近づき、攻撃を受け、暴行を受けました。
“And a river went out of Eden to water the garden, and from thence it was parted and became into four heads” Genesis 2:10. ? The heart is located in the middle of the thoracic cavity, pointing eastward.
人々にチャンスを与えることは、人生で少し遅すぎると私は信じています。寛大に。