症状
実現したい動き
ユースケース的には以下の挙動を実現したいです。
1.買い物カゴに商品を追加する(PostMethodでデータベースに追加)
2.データベースから買い物かご情報を取得して更新して画面に表示する。
1の処理を完了したあとに2の処理を実行させたいので非同期処理を使います。
実際の動き
実際のコードでは以下の挙動になり、追加後の画面更新がなされません。
0.PostMethodと同じURIでprefligtMethodが実行される。
1.データベースから買い物かご情報を取得して更新して画面に表示する。(GETMethodでデータベースから情報取得)
2.買い物カゴに商品を追加する(PostMethodでデータベースに追加)
画面更新後にデータベースに追加されるので期待している挙動ができません。
googleChromeの検証ツール結果の画像(赤丸部のリクエストがそれに該当)
preflight(OPTIONS Request Mehod)
↓
all(全取得 GET Request Method)
↓
add(POST Request Method)
という順番で実行される
開発環境
IDE:VScode
├── @types/node@18.11.15
├── @types/react-dom@18.0.9
├── @types/react@18.0.26
├── axios@1.2.1
├── eslint-config-next@13.0.6
├── eslint@8.29.0
├── next-auth@4.18.7
├── next@13.0.6
├── react-bootstrap@2.7.0
├── react-dom@18.2.0
├── react@18.2.0
├── styled-components@5.3.6
├── styled-jsx@5.1.1
└── typescript@4.9.4
ソースコード
const [currentCartItems, setCurrentCartItems] = useState<CartItem[]>([]);
const [jwtAccessToken, setJwtAccessToken] = useState<string | null>();
const getCartItems = () => {
cartItemService
.getCartItems(jwtAccessToken as string)
.then((response) => {
// 再レンダリングを防ぐために、レスポンスのデータが変わっている場合のみsetCurrentCartItemsを実行する。
if (
(response.data as CartItem[]).toString() !=
currentCartItems.toString()
) {
setCurrentCartItems(response.data);
console.log(response.data);
}
console.log("cartItems are set");
})
.catch((error) => {
console.log("cartItems are not set");
});
};
let inputProductId: number = 0;
let inputQuantity: number = 0;
const addCartItem = () => {
const inputCartItem: CartItem = {
// productId: inputProductId as number, quantity: inputQuantity as number,
productId: inputProductId as number,
quantity: inputQuantity as number,
id: 0,
customerId: 0,
};
cartItemService
.addProductCart(inputCartItem, jwtAccessToken as string)
.then((response) => {
console.log(response.data);
console.log("cartItems is added");
})
.catch((error) => {
console.log("cartItems are not set");
});
};
// データベースに追加後、データベースから再取得する
const addCartItemHandler = async () => {
console.log("jwt" + jwtAccessToken);
await addCartItem();
console.log("between addCartItem and getCartItems");
await getCartItems();
//addCartItem実行後に getCartItemが実行されない
// preflightとやらがきて 実際の処理が実行されない
};
import axios from 'axios';
import { CartItem } from '../types/cartItem';
/**
*
* @remarks SpringBootで作ったAPIを呼ぶ関数
*
*
* @param jwtAccessKey
* @returns
*/
export const addProductCart = ({productId,quantity}: CartItem, jwtAccessKey:string) =>{
return axios.post(`http://127.0.0.1:5000/api/cart/add`
+ `?productId=` +productId
+ `&quantity=` +quantity
,{},
{ headers : {
'Authorization': `Bearer ${jwtAccessKey}`,
'Request-Method' : 'POST',
'Content-Type': 'application/json',
'Access-Control-Allow-Origin': 'http://127.0.0.1:5000/*',
'Access-Control-Allow-Headers': 'accept, accept-language, content-language, content-type',
'Access-Control-Allow-Credentials': 'true'
}}
);
}
//
export const getCartItems =(jwtAccessKey : string)=>{
return axios.get(`http://127.0.0.1:5000/api/cart/all`,
{ headers : {
'Authorization': `Bearer ${jwtAccessKey}`
}}
);
}
//
export const updateQuantity = ({productId,quantity}:CartItem,jwtAccessKey:string) =>{
return axios.put(`http://127.0.0.1:5000/api/cart/update`
+ `?productId=` +productId
+ `&quantity=` +quantity,
{ headers : {
'Authorization': `Bearer ${jwtAccessKey}`
}}
)
}
export const removeProduct = ({productId}:CartItem, jwtAccessKey:string) =>{
return axios.delete(`http://127.0.0.1:5000/api/cart/remove`
+`?productId=`+ productId,
{ headers : {
'Authorization': `Bearer ${jwtAccessKey}`
}}
);
}
export const deleteByCustomer = (jwtAccessKey:string) =>{
return axios.delete(`http://127.0.0.1:5000/api/cart/delete`,
{ headers : {
'Authorization': `Bearer ${jwtAccessKey}`
}}
);
}
対処方法
方針としてはpreflightリクエストのあとにPostリクエストが実行するようにします。
実装方法としては、addCartItemの処理にasync awaitを追加しただけです。
修正後のソースコード
- const addCartItem = () => {
+ const addCartItem = async () => { //asyncの理由 preflight処理が発生しても実行順序守らせるために必要
const inputCartItem: CartItem = {
// productId: inputProductId as number, quantity: inputQuantity as number,
productId: inputProductId as number,
quantity: inputQuantity as number,
id: 0,
customerId: 0,
};
- cartItemService
+ await cartItemService //awaitの理由 preflight処理が発生しても実行順序守らせるために必要
.addProductCart(inputCartItem, jwtAccessToken as string)
.then((response) => {
console.log(response.data);
console.log("cartItems is added");
})
.catch((error) => {
console.log("cartItems are not set");
});
};
下のソースコードだけでは不十分みたいですね。
// データベースに追加後、データベースから再取得する
const addCartItemHandler = async () => {
console.log("jwt" + jwtAccessToken);
await addCartItem();
console.log("between addCartItem and getCartItems");
await getCartItems();
//addCartItem実行後に getCartItemが実行されない
// preflightとやらがきて 実際の処理が実行されない
};
確認
preflight(OPTIONS Request Mehod)
↓
add(POST Request Method)
↓
all(全取得 GET Request Method)
となっております。よし!期待した動きをしてるな!
参考
COR関わりの現象みたいですね。