首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >与后端响应初始化和同步状态

与后端响应初始化和同步状态
EN

Stack Overflow用户
提问于 2020-06-04 18:55:35
回答 2查看 774关注 0票数 1

我想知道初始化状态并保持状态与服务器同步的最佳方式/模式是什么。在过去的几天里,我阅读和尝试了很多,但是没有发现任何解决我问题的方法。

这个例子真的很简单。为了简单起见,示例中有一种状态--它是一个数字,尽管在现实生活中它将是一个对象--我需要从服务器中检索它。一旦检索到,我希望它与服务器同步。getValueFromServer是一个模拟,它在setTimeout中等待随机时间之后返回一个随机值。

因此,要初始化我的状态,我使用空数组上的useEffect作为依赖项,为了保持同步,我使用状态作为依赖项的useEffect。

问题在于它试图保存一个未定义的值。日志如下。

1 ->首次初始化

2保存服务器值的-> API调用:未定义

3保存服务器值的-> API调用: 6.026930847574949

我得到的是:

1:按预期运行。

他说:这个我没料到。我想它是因为"useState“而触发的。

3:一旦从服务器获得响应,就运行。这很明显,但很痛苦,因为我到底为什么想要拯救这个。

这里最好的办法是什么?在带有依赖关系的useEffect中使用类似于“useEffect”标志的东西会让人感觉有点被黑了,而不是专业的。

下面的代码,您可以发现它也在这里工作:https://codesandbox.io/s/optimistic-rgb-uce9f

代码语言:javascript
复制
import React, { useState, useEffect } from "react";
import { getValueFromServer } from "./api";

export default function App() {
  const [value, setValue] = useState();

  useEffect(() => {
    async function initialize() {
      console.log("Initializing for first time");
      let serverValue = await getValueFromServer();
      setValue(serverValue);
    }
    initialize();
  }, []);

  useEffect(() => {
    console.log("API call to save in server value: ", value);
  }, [value]);

  const handleClick = () => {
    setValue(value + 1);
  };

  return (
    <div className="App">
      <h1>Value: {value}</h1>
      <button onClick={handleClick}>Add 1 to value</button>
    </div>
  );
}
EN

回答 2

Stack Overflow用户

回答已采纳

发布于 2020-06-04 19:17:55

,这里最好的方法是什么?在带有依赖关系的useEffect中使用类似于“useEffect”标志的东西会让人感觉有点被黑了,而不是专业的。

您可以在useState中使用标志或使用默认值初始化对象。

代码语言:javascript
复制
const { Fragment, useState, useEffect } = React;

const getValueFromServer = () => new Promise((resolve, reject) => setTimeout(() => resolve(Math.random())), 1000)

const App = () => {
  const [value, setValue] = useState(null);
  const [isLoading, setLoading] = useState(true);

  useEffect(() => {
    let isUnmounted = false;
  
    getValueFromServer().then(serverValue => {
      console.log("Initializing for first time");
      if(isUnmounted) {
        return;
      }
      setValue(serverValue);
      setLoading(false);
    })
    
    return () => {
      isUnmounted = true;
    }
  }, []);

  useEffect(() => {
    if(!value) {
      return () => {}
    }
  
    console.log("API call to save in server value: ", value);
    setTimeout(() => setLoading(false), 50);
  }, [value]);

  const handleClick = () => {
    setLoading(true);
    setValue(value + 1);
  };

  return <div className="App">
    {isLoading ? <Fragment>
      <span>Loading...</span>
    </Fragment> : <Fragment>
      <h1>Value: {value}</h1>
      <button onClick={handleClick}>Add 1 to value</button>
    </Fragment>}
  </div>
}

ReactDOM.render(
    <App />,
    document.getElementById('root')
  );
代码语言:javascript
复制
<script src="https://unpkg.com/react/umd/react.development.js"></script>
<script src="https://unpkg.com/react-dom/umd/react-dom.development.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/babel-polyfill/7.10.1/polyfill.js"></script>
<script src="https://unpkg.com/babel-standalone@6/babel.min.js"></script>
<div id="root"></div>

票数 1
EN

Stack Overflow用户

发布于 2020-06-04 19:17:12

您的应用程序在忙着await处理第一个useEffect钩子函数中发生的事情时做其他的事情。本例中的“其他内容”是“执行第二个useEffect钩子函数”。此时没有定义serverValue,因此也没有定义value,因此console.log打印undefined。一旦您的await承诺解析为一个值并调用了setValue,您的第二个useEffect钩子函数的依赖项就会发生变化,导致您的函数再次运行(并打印出您期望的值)。

如果您必须有两个useEffect挂钩,那么当value未定义时,只需退出第二个钩子:

代码语言:javascript
复制
  useEffect(() => {
    if (value === undefined) {
      return;
    }

    console.log('value is:', value);
  }, [ value ]);
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/62202159

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档