javascript - React Store 没有第一次返回 getMethod 的值
问题描述
我是 React、Mobx 堆栈的新手。我遇到了一个问题,即我的商店在第一次调用后没有立即反映其价值。当我进行第二次调用时,它返回第一个值。我无法理解为什么会发生这种情况,因为我在 React、Mobx 堆栈方面还有很长的路要走。
我的商店课程
export default class ServiceTemplateStore {
loadingInitial = false;
serviceTemplateDetail: any | undefined;
constructor() {
makeAutoObservable(this)
}
setLoadingInitial = (state: boolean) => {
this.loadingInitial = state;
}
get getServiceTemplateDetail() {
return this.serviceTemplateDetail;
}
loadServiceTemplateDetail = async (id: string) => {
this.loadingInitial = true;
try {
const serviceTemplateDetail = await agent.serviceTemplateDetail.details(id);
runInAction(() => {
console.log("Service loaded");
this.serviceTemplateDetail = serviceTemplateDetail;
console.log(this.serviceTemplateDetail); //Here I can see it immediately outputs the value.
this.setLoadingInitial(false);
});
} catch (error) {
console.log(error);
this.setLoadingInitial(false);
}
}
}
子组件
这是我使用 Store 的地方,当我使用useEffect
Hook 时,它实际上会填充数据,但是当我在内部onClick
函数中运行时,它不会填充值。
我的理解是 AxiosGET
调用按预期执行,它还返回值并将其分配给serviceTemplateDetail
变量。但是当我通过getServiceTemplateDetail
方法访问该值时,它第一次返回 null,当我下次单击 Import 按钮时,它返回从GET
Request返回的旧值
import DataGrid, { Selection } from "devextreme-react/data-grid";
import Popup, { Position, ToolbarItem } from "devextreme-react/popup";
import { Column } from "devextreme-react/tree-list";
import { observer } from "mobx-react-lite";
import React, { Component, useCallback, useEffect, useState } from 'react'
import { useStore } from "../store/Store";
export default observer(function ImportServiceTemplate(props: importServiceProp) {
const [ serviceTemplateIds, setServiceTemplateIds] = useState([]);
const { serviceTemplateStore } = useStore();
const { serviceTemplateList, loadServiceTemplateList, loadServiceTemplateDetail, getServiceTemplateDetail, serviceTemplateDetail } = serviceTemplateStore;
useEffect(() => {
if (serviceTemplateList?.length === 0 || serviceTemplateList === undefined) loadServiceTemplateList();
}, [loadServiceTemplateList])
const closeButtonOption = {
icon: 'close',
text: 'Close',
onClick: ()=>{
props.onCloseImportModel();
}
};
//Added a useEffect to test..
//UseEffect returns the value but not my Import function below
useEffect(() => {
console.log("use effect");
console.log(JSON.stringify(getServiceTemplateDetail));
}, [getServiceTemplateDetail])
//Actual function that needs to work.
const importButtonOption = {
icon: 'download',
text: 'Import',
onClick: () => {
if(serviceTemplateIds){
loadServiceTemplateDetail(String(serviceTemplateIds))
.then(()=>{
console.log("Callback");
console.log(JSON.stringify(serviceTemplateDetail)); // Getting undefined as output.
props.importingServiceTemplate(getServiceTemplateDetail); //Passing the imported value to parent component
});
}
}
};
const onSelectionChanged = (e: any) => {
console.log("Processing", e.selectedRowKeys);
setServiceTemplateIds(e.selectedRowKeys);
};
return (
<>
<Popup
visible={props.isImportVisible}
dragEnabled={false}
closeOnOutsideClick={false}
showCloseButton={false}
showTitle={true}
title="Service Template"
width={800}
height={280}>
<Position
at="center"
my="center"
/>
<DataGrid
id="serviceTemplateGrid"
key="ServiceTemplateId"
keyExpr="ServiceTemplateId"
focusedRowEnabled={true}
onSelectionChanged={onSelectionChanged}
selectedRowKeys={serviceTemplateIds}
dataSource={serviceTemplateList}
showRowLines={true}
showBorders={true}>
<Selection mode="multiple" showCheckBoxesMode="onClick" />
<Column dataField="Name" caption="Name" />
<Column dataField="CustomerName" caption="Customer Name" />
<Column dataField="BaseCurrencyCode" caption="Currency" />
<Column dataField="Description" caption="Description" />
</DataGrid>
<ToolbarItem
widget="dxButton"
toolbar="bottom"
location="before"
options={closeButtonOption}
/>
<ToolbarItem
widget="dxButton"
toolbar="bottom"
location="after"
options={importButtonOption}
/>
<div>{JSON.stringify(getServiceTemplateDetail)}</div>
</Popup>
</>
)
})
interface importServiceProp{
isImportVisible: boolean;
onCloseImportModel: Function
importingServiceTemplate: any
}
解决方案
这不是 React 或 MobX 问题,只是一个常规的 javascript 闭包。
当您创建importButtonOption
函数时,它remembers
周围的所有变量,并且serviceTemplateDetail
在第一次等于未定义。loadServiceTemplateDetail
serviceTemplateDetail
因此,在 store 中更改了调用后,但在importButtonOption
函数内部,它仍然remembered
是创建函数时的旧值。
希望这是有道理的。基本上你只需要阅读闭包以及它们是如何工作的。
React 文档中有一个小指南
例如,您可以做的是删除值的解构并根据需要取消引用它们,如下所示:
loadServiceTemplateDetail(String(serviceTemplateIds))
.then(()=>{
console.log("Callback");
console.log(JSON.stringify(serviceTemplateStore .serviceTemplateDetail)); // reference it from the store to get actual value
props.importingServiceTemplate(getServiceTemplateDetail); //Passing the imported value to parent component
});
推荐阅读
- r - data.table 具有时间窗的不规则观测的累积统计数据
- java - 用于多个/所有变量/集合的单个 getter 函数
- c# - 如何改变状态 = new OpenState(); 在 time_elapsed 方法中反映内存中状态对象的更改
- php - 在查询之前更改自动提交并在之后重置它
- php - 如果在 Laravel API 端启用 opCache,随机 CORS 请求将失败
- c# - MSDN SafeHandle 示例
- python - 如何防止文本文件在 Python 3 中被重命名?
- amazon-web-services - 将 ENI 附加到任何给定实例后如何启用网络接口
- java - 将可选存在转换为哈希映射到面向对象的设计
- karate - 空手道加特林在使用加特林的油门功能时抛出异常并且没有生成报告