更新从api接收到的客户端状态,而不在redux中刷新



我有两个功能,一个是发送订单,更新用户余额,另一个是检索用户余额,供用户查看。在任何订单发生之前,我仍然需要检索余额供用户查看,因此我已经从MarketLongFunc断开了getBalance函数。

使用redux工具箱和redux thunk,我有一个ordersSlice.js,看起来像这样:

export const MarketLongFunc = createAsyncThunk(
"/order/marketlong",
async (value, thunkAPI) => {
const token = thunkAPI.getState().auth.user.token;
const newObj = {
value: value,
token: token,
};
let url = `http://localhost:3001/api/orders/marketlong`;
const response = await axios.post(url, newObj);
//getBalance() 
return;
}
);


export const getBalance = createAsyncThunk(
"/order/getBalance",
async (value, thunkAPI) => {
const token = thunkAPI.getState().auth.user.token;
const newObj = {
token: token,
};
let url = `http://localhost:3001/api/orders/getBalance`;
const response = await axios.post(url, newObj);
return response.data;
}
);
const initialState = {
value: null,
error: null,
balance: null,
status: "idle",
orderStatus: "idle",
};
export const ordersSlice = createSlice({
name: "orders",
initialState,
reducers: {
reset: (state) => initialState,
resetStatus: (state) => {
state.orderStatus = "idle";
},
},
extraReducers(builder) {
builder
.addCase(MarketLongFunc.pending, (state, action) => {
state.orderStatus = "loading";
})
.addCase(MarketLongFunc.fulfilled, (state, action) => {
state.orderStatus = "success";
// getBalance();
// state.balance = action.payload;
})
.addCase(MarketLongFunc.rejected, (state, action) => {
state.orderStatus = "failed";
state.error = action.error.message;
})
.addCase(getBalance.pending, (state, action) => {
state.status = "loading";
})
.addCase(getBalance.fulfilled, (state, action) => {
// state.status = "success";
state.balance = action.payload;
state.status = "success";
})
.addCase(getBalance.rejected, (state, action) => {
state.status = "failed";
state.error = action.error.message;
});
},
});
export const { reset } = ordersSlice.actions;
export default ordersSlice.reducer;

现在,在我的下一个组件中,如果还没有余额,并且用户已经登录,useEffect将调用。我试图解决问题的方法是在MarketLongFunc.fulfilled下使用state.orderStatus = "success",这种方式假设如果放置MarketLong,我可以在useEffect下调度getbalance,然后通过重置来更改状态,如下所示:

export const Orderform = () => {
const user = useSelector((state) => state.auth.user);
const balance = useSelector((state) => state.orders.balance);
const status = useSelector((state) => state.orders.orderStatus);
const dispatch = useDispatch();

useEffect(() => {
if (!balance && user) {
dispatch(getBalance());
}
if (status == "success") {
dispatch(getBalance());
dispatch(resetStatus());
}
}, [balance]);
if (user) {
return (
<div>
<h1>
cash balance: ${balance ? Math.round(balance.balance) : "error"}
</h1>
<MarketLong />
</div>
);
}
return (
<div>
Login
</div>
);
};

上述代码目前不起作用,因为当我刷新时的console.log(status)idle,当我使用marketLong时是loading,但它从未实现,所以更新订单后显示的余额的唯一方法仍然是刷新页面。我想在不刷新页面的情况下更新显示的余额,因为刷新页面必须在getBalance上进行另外两个API调用。我在尝试将CCD_ 11函数放入ordersSlice中的CCD_,我也尝试过返回它等,但没有起到任何作用,我认为在useEffect中用状态"修复这个问题将是解决这个问题的最佳方法,但我愿意听到其他解决方案,除了创建冗余代码之外,我基本上只是在marketLongFunc中键入getBalance函数。

另一种几乎有效的方法是在我的MarketLong反应组件中的dispatch(MarketLongFunc(longItem));之后添加dispatch(getBalance()),如下所示:

const addNewLong = async (e) => {
e.preventDefault();
const longItem = {
userInput: req.ticker,
quotePrice: req.quotePrice,
quantity: Item.quantity,
};
dispatch(MarketLongFunc(longItem));
dispatch(getBalance());
};

问题是,第一个订单永远不会更新,但在那之后,它会错误地更新,因为一个购买订单会使余额减少。我想这是由于在MarketLongFunc之前调用了getBalance,但没有设置手动setTimeout函数,这似乎是一个笨拙的解决方案,我不确定如何使用redux来解决这个问题,你可能会想:if (dispatch(MarketLongFunc(longItem))) {dispatch(getBalance())},但也许这种方式需要在ordersSlice中更改(我已经尝试过,但无法使其工作(。

有很多方法可以解决这个问题-我将描述一个近似的解决方案:

export const MarketLongFunc = createAsyncThunk(
"/order/marketlong",
async (value, thunkAPI) => {
const token = thunkAPI.getState().auth.user.token;
const newObj = {
value: value,
token: token,
};
let url = `http://localhost:3001/api/orders/marketlong`;
const response = await axios.post(url, newObj);
//getBalance() 
return;
}
);


export const getBalance = createAsyncThunk(
"/order/getBalance",
async (value, thunkAPI) => {
const token = thunkAPI.getState().auth.user.token;
const newObj = {
token: token,
};
let url = `http://localhost:3001/api/orders/getBalance`;
const response = await axios.post(url, newObj);
return response.data;
}
);
const initialState = {
value: null,
error: null,
balance: null,
status: "idle",
orderStatus: "idle",
balanceNeedsToBeUpdated: true // <--- HERE
};
export const ordersSlice = createSlice({
name: "orders",
initialState,
reducers: {
reset: (state) => initialState,
},
extraReducers(builder) {
builder
.addCase(MarketLongFunc.pending, (state, action) => {
state.orderStatus = "loading";
})
.addCase(MarketLongFunc.fulfilled, (state, action) => {
state.orderStatus = "idle";
state.balanceNeedsToBeUpdated = true; // < ----- HERE
// getBalance();
// state.balance = action.payload;
})
.addCase(MarketLongFunc.rejected, (state, action) => {
state.orderStatus = "failed";
state.error = action.error.message;
})
.addCase(getBalance.pending, (state, action) => {
state.status = "loading";
})
.addCase(getBalance.fulfilled, (state, action) => {
// state.status = "success";
state.balance = action.payload;
state.status = "idle";
state.balanceNeedsToBeUpdated = false; // <---- HERE
})
.addCase(getBalance.rejected, (state, action) => {
state.status = "failed";
state.error = action.error.message;
});
},
});
export const { reset } = ordersSlice.actions;
export default ordersSlice.reducer;
export const Orderform = () => {
const user = useSelector((state) => state.auth.user);
const balance = useSelector((state) => state.orders.balance);
const status = useSelector((state) => state.orders.status);
const orderStatus = useSelector((state) => state.orders.orderStatus);
const balanceNeedsToBeUpdated = useSelector((state) => state.orders.balanceNeedsToBeUpdated);
const dispatch = useDispatch();

useEffect(() => {
if (user && balanceNeedsToBeUpdated) { //< ----- HERE
dispatch(getBalance());
}
}, [user, balanceNeedsToBeUpdated]); // < ---- HERE
if (user) {
if (status == 'loading' || orderStatus == 'loading') {
return <div>loading</div>;
}

return (
<div>
<h1>
cash balance: ${balance ? Math.round(balance.balance) : "error"}
</h1>
<MarketLong />
</div>
);
}
return (
<div>
Login
</div>
);
};
//....
const addNewLong = async (e) => {
e.preventDefault();
const longItem = {
userInput: req.ticker,
quotePrice: req.quotePrice,
quantity: Item.quantity,
};
dispatch(MarketLongFunc(longItem)); // < --- HERE
};

最新更新