Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/wordpress/11.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript 在promise resolve方法中,状态总是过时的_Javascript_Reactjs_State_State Management - Fatal编程技术网

Javascript 在promise resolve方法中,状态总是过时的

Javascript 在promise resolve方法中,状态总是过时的,javascript,reactjs,state,state-management,Javascript,Reactjs,State,State Management,所以我的水疗中心遇到了一个关于州的奇怪问题 我有一个左边的菜单,上面有项目,比如说组织,当我点击其中任何一个项目时,右边的面板会随着所选组织中相应的用户列表而改变 例如:我在列表中有组织1和组织2,如果我单击组织1,我会向中间件发送请求以检索该组织中的用户列表,如果我选择组织2,我也会这样做 因此,我有一个更高的组件Organization.js,其代码如下:- // Organization.js const [selectedOrganization, setSelectedOrganiz

所以我的水疗中心遇到了一个关于州的奇怪问题

我有一个左边的菜单,上面有项目,比如说组织,当我点击其中任何一个项目时,右边的面板会随着所选组织中相应的用户列表而改变

例如:我在列表中有组织1和组织2,如果我单击组织1,我会向中间件发送请求以检索该组织中的用户列表,如果我选择组织2,我也会这样做

因此,我有一个更高的组件Organization.js,其代码如下:-

// Organization.js

const [selectedOrganization, setSelectedOrganization] = useState(null);

// This method will be called when we select an organization from the menu

const handleSelectedOrganization = organization => {
if (!selectedOrganization || selectedOrganization.id !== organization.id) {
  setSelectedOrganization(organization);
 }
};

return (
     <UsersView selectedOrganization={selectedOrganization} />
);
//Organization.js
const[selectedOrganization,setSelectedOrganization]=useState(null);
//当我们从菜单中选择组织时,将调用此方法
const handleSelectedOrganization=组织=>{
如果(!selectedOrganization | | selectedOrganization.id!==organization.id){
设置选定的组织(组织);
}
};
返回(
);
UsersView.js

const UsersView = ({ selectedOrganization = {} }) => {

  const [selectedOrganizationUsers, setSelectedOrganizationUsers] = useState(
[]);
let globalOrganization = selectedOrganization?.id; // global var

const refreshOrganizationsList = () => {
const localOrganization = selectedOrganization.id; // local var
Promise.all([ // bunch of requests here]).then(data => {
  console.log('from global var', globalOrganization); // outdated
  console.log('from local var', localOrganization); // outdated
  console.log('from prop', selectedOrganization.id); // outdated
  setSelectedOrganizationUsers(data.result); // data.result is an array of objects
});
};


// Will be called when the selectedOrganization prop changes, basically when I select
//a new organization from the menu, the higher component will
// change state that will reflect here since the prop will change.
useEffect(() => {
if (selectedOrganization) {
  globalOrganization = selectedOrganization.id;
  refreshOrganizationsList();
}
}, [selectedOrganization]);

console.log(selectedOrganization?.id); // Always updated *1

return (
{selectedOrganizationUsers?.length ? (
        <>
          <div className="headers">
          ....
)
constusersview=({selectedOrganization={}})=>{
常量[selectedOrganizationUsers,setSelectedOrganizationUsers]=useState(
[]);
让globalOrganization=selectedOrganization?.id;//全局变量
常量刷新组织列表=()=>{
const localOrganization=selectedOrganization.id;//本地变量
Promise.all([//这里有一堆请求])。然后(data=>{
log('from global var',globalOrganization);//过时
console.log('from local var',localOrganization);//过时
console.log('from prop',selectedOrganization.id);//过时
setSelectedOrganizationUsers(data.result);//data.result是一个对象数组
});
};
//将在selectedOrganization道具更改时调用,基本上是在我选择
//从菜单中选择一个新的组织,将显示更高的组件
//由于道具将发生更改,因此将在此处反映的更改状态。
useffect(()=>{
如果(已选择组织){
globalOrganization=selectedOrganization.id;
刷新组织列表();
}
},[selectedOrganization]);
console.log(selectedOrganization?.id);//始终更新*1
返回(
{selectedOrganizationUsers?。长度(
....
)
现在的问题是,一些API调用需要很长时间才能响应,在一个特定的场景中,当我在Org fast之间切换时,我们会得到一些挂起的API调用,当响应到来时,状态就会混乱

例如:如果我从菜单Organization 1中选择,我们将向中间件发送3个请求,这些请求将保持挂起状态,比如说10秒钟

如果在5秒钟后,我从菜单中选择Organization 2,其API请求将是即时的,则右侧面板将使用Organization 2数据更新,但在5秒钟后,当Organization 1请求获得响应时,列表将使用Organization 1数据更新,这是我尝试阻止的,因为现在我们选择了或组织2

之所以在.then()中有console.logs,是因为当当前选择的organization!==响应中的organization.id时,我试图阻止更新状态

但不幸的是,上述场景中的console.logs会将组织id设置为1而不是2,即使我已经选择了组织2

例如:

我选择了组织1,然后选择了组织2

选择Organization 2后,outside*1 console.log将立即在我的浏览器中记录2

但是当我得到1的API响应时,.then()中的console.logs会给我1而不是2,我希望他们会给我2,这样我就可以做一个if(request.organization\u id!==selectedOrganization.id)->不更新状态

长话短说,似乎当API调用返回结果时,.then()中的organization.id始终是我们启动请求本身时的状态,而不是最新的部分。好像它不再与来自更高组件状态的道具中的最新值相关联

使用函数更新程序函数与最新状态进行比较 因此,一个可能的解决方案与之密切相关,尽管一开始可能并不那么明显

首先,您需要稍微更改状态结构。如果随着时间的推移变得太复杂,您可能需要查看、或一个完整的状态管理库,如Redux或类似的库

然后,使用functional updater函数与最新状态值进行比较,如果所选组织已经更改,则最新状态值可能已经更改

const UsersView = ({ selectedOrganization }) => {
  // Slightly change the state structure.
  const [{ users }, setState] = useState({
    currentOrgId: selectedOrganization?.id,
    users: [],
  });

  const refreshOrganizationsList = (orgId) => {
    // Set the currentOrgId in the state so we remember which org was the last fetch for.
    setState((state) => ({ ...state, currentOrgId: orgId }));

    Promise.all([
      /* bunch of requests here */
    ]).then((data) => {
      setSelectedOrganizationUsers((state) => {
        // Is the current org still the one we started the fetch for?
        if (state.currentOrgId !== orgId) {
          // Precondition failed? Early return without updating the state.
          return state;
        }

        // Happy path, update the state.
        return {
          ...state,
          users: data.result,
        };
      });
    });
  };

  useEffect(() => {
    if (selectedOrganization) {
      // instead of a component scoped variable, just pass the id as a param.
      refreshOrganizationsList(selectedOrganization.id);
    }
  }, [selectedOrganization]);

  return (/* JSX here */);
};

不再需要局部变量。事实上,闭包会捕获局部变量,即使组件再次呈现,值也不会在旧的
refreshOrganizationsList
函数引用(每个呈现周期都会重新创建)中更改.

这是否回答了您的问题?虽然它可能不是非常清楚,但您可以在updater函数中添加条件,以检查它是否仍然与您刚收到的组织数据相关,或者是否太迟了。例如,
setSelectedOrganization(currentOrg=>IsStillRelated?newOrg:currentOrg)
@EmileBergeron不太可能。这对我的情况没有帮助,我知道它的功能setState@EmileBergeron关于你的第二条评论。我不想阻止组织选择本身,我希望组织选择能够起作用,但由于API调用响应时间,我会阻止右侧的错误状态更新。这对我来说更容易在我们得到响应之前阻止任何组织选择,但我不想这样做,至少除非我没有任何选择..将
selectedOrganization
作为参数传递给
refreshOrganizationsList()
,然后再试一次?你是个救命恩人!非常感谢,工作正常:).我需要更多地阅读和理解你在这里所做的事情,这将在今后的许多其他情况下对我有所帮助